Merge branch 'save-path-regex'

net8.0^2
Pat Hartl 2023-11-30 19:12:47 -06:00
commit a716bafc4d
12 changed files with 1807 additions and 53 deletions

View File

@ -13,6 +13,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Text; using System.Text;
using System.Text.RegularExpressions;
using YamlDotNet.Serialization; using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NamingConventions;
@ -60,40 +61,35 @@ namespace LANCommander.SDK
ExtractFilesFromZip(tempFile, tempLocation); ExtractFilesFromZip(tempFile, tempLocation);
var deserializer = new DeserializerBuilder()
.WithNamingConvention(new PascalCaseNamingConvention())
.Build();
#region Move files #region Move files
foreach (var savePath in manifest.SavePaths.Where(sp => sp.Type == "File")) foreach (var savePath in manifest.SavePaths.Where(sp => sp.Type == "File"))
{ {
bool inInstallDir = savePath.Path.StartsWith("{InstallDir}"); bool inInstallDir = savePath.Path.StartsWith("{InstallDir}");
string tempSavePath = Path.Combine(tempLocation, savePath.Id.ToString()); string tempSavePath = Path.Combine(tempLocation, savePath.Id.ToString());
var tempSavePathFile = Path.Combine(tempSavePath, savePath.Path.Replace('/', '\\').Replace("{InstallDir}\\", "")); foreach (var entry in savePath.Entries)
destination = Environment.ExpandEnvironmentVariables(savePath.Path.Replace('/', '\\').Replace("{InstallDir}", installDirectory));
if (File.Exists(tempSavePathFile))
{ {
// Is file, move file var tempSavePathFile = Path.Combine(tempSavePath, entry.ArchivePath);
if (File.Exists(destination))
File.Delete(destination);
File.Move(tempSavePathFile, destination); destination = Environment.ExpandEnvironmentVariables(entry.ActualPath).Replace("{InstallDir}", installDirectory);
}
else if (Directory.Exists(tempSavePath))
{
var files = Directory.GetFiles(tempSavePath, "*", SearchOption.AllDirectories);
if (inInstallDir) if (File.Exists(tempSavePathFile))
{ {
if (File.Exists(destination))
File.Delete(destination);
File.Move(tempSavePathFile, destination);
}
else if (Directory.Exists(tempSavePath))
{
var files = Directory.GetFiles(tempSavePath, "*", SearchOption.AllDirectories);
foreach (var file in files) foreach (var file in files)
{ {
if (inInstallDir) if (inInstallDir)
{ {
// Files are in the game's install directory. Move them there from the save path. // Files are in the game's install directory. Move them there from the save path.
destination = file.Replace(tempSavePath, savePath.Path.Replace('/', '\\').TrimEnd('\\').Replace("{InstallDir}", installDirectory)); destination = file.Replace(tempSavePath, savePath.Path.Replace('/', Path.DirectorySeparatorChar).TrimEnd(Path.DirectorySeparatorChar).Replace("{InstallDir}", installDirectory));
if (File.Exists(destination)) if (File.Exists(destination))
File.Delete(destination); File.Delete(destination);
@ -103,7 +99,7 @@ namespace LANCommander.SDK
else else
{ {
// Specified path is probably an absolute path, maybe with environment variables. // Specified path is probably an absolute path, maybe with environment variables.
destination = Environment.ExpandEnvironmentVariables(file.Replace(tempSavePathFile, savePath.Path.Replace('/', '\\'))); destination = Environment.ExpandEnvironmentVariables(file.Replace(tempSavePathFile, savePath.Path.Replace('/', Path.DirectorySeparatorChar)));
if (File.Exists(destination)) if (File.Exists(destination))
File.Delete(destination); File.Delete(destination);
@ -112,10 +108,6 @@ namespace LANCommander.SDK
} }
} }
} }
else
{
}
} }
} }
#endregion #endregion
@ -163,31 +155,42 @@ namespace LANCommander.SDK
#region Add files from defined paths #region Add files from defined paths
foreach (var savePath in manifest.SavePaths.Where(sp => sp.Type == "File")) foreach (var savePath in manifest.SavePaths.Where(sp => sp.Type == "File"))
{ {
var localPath = Environment.ExpandEnvironmentVariables(savePath.Path.Replace('/', '\\').Replace("{InstallDir}", installDirectory)); IEnumerable<string> localPaths;
if (Directory.Exists(localPath)) if (savePath.IsRegex)
{ {
AddDirectoryToZip(archive, localPath, localPath, savePath.Id); var regex = new Regex(Environment.ExpandEnvironmentVariables(savePath.Path.Replace('/', '\\').Replace("{InstallDir}", installDirectory)));
localPaths = Directory.GetFiles(installDirectory, "*", SearchOption.AllDirectories)
.Where(p => regex.IsMatch(p))
.ToList();
} }
else if (File.Exists(localPath)) else
{ localPaths = new string[] { savePath.Path };
archive.AddEntry(Path.Combine(savePath.Id.ToString(), savePath.Path.Replace("{InstallDir}/", "")), localPath);
}
}
#endregion
#region Add files from defined paths var entries = new List<SavePathEntry>();
foreach (var savePath in manifest.SavePaths.Where(sp => sp.Type == "File"))
{
var localPath = Environment.ExpandEnvironmentVariables(savePath.Path.Replace('/', '\\').Replace("{InstallDir}", installDirectory));
if (Directory.Exists(localPath)) foreach (var localPath in localPaths)
{ {
AddDirectoryToZip(archive, localPath, localPath, savePath.Id); var actualPath = Environment.ExpandEnvironmentVariables(savePath.Path.Replace('/', Path.DirectorySeparatorChar).Replace("{InstallDir}", installDirectory));
} var relativePath = actualPath.Replace(installDirectory + Path.DirectorySeparatorChar, "");
else if (File.Exists(localPath))
{ if (Directory.Exists(actualPath))
archive.AddEntry(Path.Combine(savePath.Id.ToString(), savePath.Path.Replace("{InstallDir}/", "")), localPath); {
AddDirectoryToZip(archive, relativePath, actualPath, savePath.Id);
}
else if (File.Exists(actualPath))
{
archive.AddEntry(Path.Combine(savePath.Id.ToString(), relativePath), actualPath);
}
entries.Add(new SavePathEntry
{
ArchivePath = relativePath,
ActualPath = actualPath.Replace(installDirectory, "{InstallDir}")
});
savePath.Entries = entries;
} }
} }
#endregion #endregion
@ -225,7 +228,11 @@ namespace LANCommander.SDK
} }
#endregion #endregion
archive.AddEntry("_manifest.yml", ManifestHelper.GetPath(installDirectory)); var tempManifest = Path.GetTempFileName();
File.WriteAllText(tempManifest, ManifestHelper.Serialize(manifest));
archive.AddEntry("_manifest.yml", tempManifest);
using (var ms = new MemoryStream()) using (var ms = new MemoryStream())
{ {

View File

@ -43,13 +43,7 @@ namespace LANCommander.SDK.Helpers
Logger?.LogTrace("Attempting to write manifest to path {Destination}", destination); Logger?.LogTrace("Attempting to write manifest to path {Destination}", destination);
var serializer = new SerializerBuilder() var yaml = Serialize(manifest);
.WithNamingConvention(new PascalCaseNamingConvention())
.Build();
Logger?.LogTrace("Serializing manifest");
var yaml = serializer.Serialize(manifest);
Logger?.LogTrace("Writing manifest file"); Logger?.LogTrace("Writing manifest file");
@ -58,6 +52,19 @@ namespace LANCommander.SDK.Helpers
return destination; return destination;
} }
public static string Serialize(GameManifest manifest)
{
var serializer = new SerializerBuilder()
.WithNamingConvention(new PascalCaseNamingConvention())
.Build();
Logger?.LogTrace("Serializing manifest");
var yaml = serializer.Serialize(manifest);
return yaml;
}
public static string GetPath(string installDirectory) public static string GetPath(string installDirectory)
{ {
return Path.Combine(installDirectory, ManifestFilename); return Path.Combine(installDirectory, ManifestFilename);

View File

@ -47,5 +47,13 @@ namespace LANCommander.SDK
public Guid Id { get; set; } public Guid Id { get; set; }
public string Type { get; set; } public string Type { get; set; }
public string Path { get; set; } public string Path { get; set; }
public bool IsRegex { get; set; }
public IEnumerable<SavePathEntry> Entries { get; set; }
}
public class SavePathEntry
{
public string ArchivePath { get; set; }
public string ActualPath { get; set; }
} }
} }

View File

@ -9,6 +9,7 @@ namespace LANCommander.SDK.Models
{ {
public SavePathType Type { get; set; } public SavePathType Type { get; set; }
public string Path { get; set; } public string Path { get; set; }
public bool IsRegex { get; set; }
public virtual Game Game { get; set; } public virtual Game Game { get; set; }
} }
} }

View File

@ -30,7 +30,7 @@ namespace LANCommander.Controllers
if (!System.IO.File.Exists(filename)) if (!System.IO.File.Exists(filename))
return NotFound(); return NotFound();
return File(new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read), "application/zip", $"{save.User?.UserName} - {save.Game?.Title} - {save.CreatedOn.ToString("MM-dd-yyyy.hh-mm")}"); return File(new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read), "application/zip", $"{save.User?.UserName} - {(save.Game == null ? "Unknown" : save.Game?.Title)} - {save.CreatedOn.ToString("MM-dd-yyyy.hh-mm")}.zip");
} }
} }
} }

View File

@ -10,6 +10,7 @@ namespace LANCommander.Data.Models
{ {
public SavePathType Type { get; set; } public SavePathType Type { get; set; }
public string Path { get; set; } public string Path { get; set; }
public bool IsRegex { get; set; }
public Guid? GameId { get; set; } public Guid? GameId { get; set; }
[JsonIgnore] [JsonIgnore]

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,29 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace LANCommander.Migrations
{
/// <inheritdoc />
public partial class AddRegexFlagToSavePath : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "IsRegex",
table: "SavePaths",
type: "INTEGER",
nullable: false,
defaultValue: false);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "IsRegex",
table: "SavePaths");
}
}
}

View File

@ -692,6 +692,9 @@ namespace LANCommander.Migrations
b.Property<Guid?>("GameId") b.Property<Guid?>("GameId")
.HasColumnType("TEXT"); .HasColumnType("TEXT");
b.Property<bool>("IsRegex")
.HasColumnType("INTEGER");
b.Property<string>("Path") b.Property<string>("Path")
.IsRequired() .IsRequired()
.HasColumnType("TEXT"); .HasColumnType("TEXT");

View File

@ -17,6 +17,9 @@
<FilePicker @bind-Value="context.Path" ArchiveId="@ArchiveId" AllowDirectories="true" /> <FilePicker @bind-Value="context.Path" ArchiveId="@ArchiveId" AllowDirectories="true" />
} }
</PropertyColumn> </PropertyColumn>
<PropertyColumn Property="p => p.IsRegex" Title="Regex">
<Checkbox @bind-Checked="context.IsRegex" />
</PropertyColumn>
<ActionColumn> <ActionColumn>
<Space Style="display: flex; justify-content: end"> <Space Style="display: flex; justify-content: end">
<SpaceItem> <SpaceItem>

View File

@ -44,7 +44,7 @@ namespace LANCommander.Services
public string GetSavePath(GameSave save) public string GetSavePath(GameSave save)
{ {
return Path.Combine(Settings.UserSaves.StoragePath, save.UserId.ToString(), $"{save.Id}.zip"); return Path.Combine(Settings.UserSaves.StoragePath, save.UserId.ToString(), $"{save.Id}");
} }
} }
} }

View File

@ -114,6 +114,7 @@ namespace LANCommander.Services
{ {
Id = p.Id, Id = p.Id,
Path = p.Path, Path = p.Path,
IsRegex = p.IsRegex,
Type = p.Type.ToString() Type = p.Type.ToString()
}); });
} }