Fix redistributable/tool importing

This commit is contained in:
Pat Hartl 2026-05-24 18:51:58 -05:00
parent 1b473343a0
commit 4965d2019b
11 changed files with 98 additions and 43 deletions

View file

@ -38,8 +38,6 @@ public class ImportContext : IDisposable
private readonly StorageLocationService _storageLocationService;
private readonly ILogger<ImportContext> _logger;
private string? _uploadedArchivePath;
#region Importers
private readonly ActionImporter _actions;
private readonly ArchiveImporter _archives;
@ -103,10 +101,8 @@ public class ImportContext : IDisposable
public void SetId(Guid id) => Id = id;
public void TrackUploadedArchive(string path) => _uploadedArchivePath = path;
#region Initialize Import
public async Task<IEnumerable<IImportItemInfo>> InitializeImportAsync(string archivePath)
public async Task<IEnumerable<IImportItemInfo>> InitializeImportAsync(string archivePath, ManifestType? manifestType = null)
{
_actions.UseContext(this);
_archives.UseContext(this);
@ -131,18 +127,18 @@ public class ImportContext : IDisposable
_servers.UseContext(this);
_tags.UseContext(this);
_tools.UseContext(this);
Archive = ZipArchive.OpenArchive(archivePath, new ReaderOptions());
var manifestEntry = Archive.Entries.FirstOrDefault(e => e.Key == ManifestHelper.ManifestFilename);
// Legacy purposes
if (manifestEntry == null)
manifestEntry = Archive.Entries.FirstOrDefault(e => e.Key == "_manifest.yml");
if (manifestEntry == null)
throw new InvalidOperationException("Invalid import file, cannot load manifest");
using (var reader = new StreamReader(manifestEntry.OpenEntryStream()))
{
var manifestContents = await reader.ReadToEndAsync();
@ -155,22 +151,50 @@ public class ImportContext : IDisposable
return await InitializeLegacyGameImportAsync(legacyGameManifest);
}
if (ManifestHelper.TryDeserialize<SDK.Models.Manifest.Game>(manifestContents, out var gameManifest))
if (manifestType.HasValue)
return await InitializeByTypeAsync(manifestType.Value, manifestContents);
if (ManifestHelper.TryDeserialize<SDK.Models.Manifest.Game>(manifestContents, out var gameManifest) && !String.IsNullOrWhiteSpace(gameManifest.Title))
return await InitializeGameImportAsync(gameManifest);
if (ManifestHelper.TryDeserialize<SDK.Models.Manifest.Redistributable>(manifestContents, out var redistributableManifest))
if (ManifestHelper.TryDeserialize<SDK.Models.Manifest.Redistributable>(manifestContents, out var redistributableManifest) && !String.IsNullOrWhiteSpace(redistributableManifest.Name))
return await InitializeRedistributableImportAsync(redistributableManifest);
if (ManifestHelper.TryDeserialize<SDK.Models.Manifest.Server>(manifestContents, out var serverManifest))
if (ManifestHelper.TryDeserialize<SDK.Models.Manifest.Server>(manifestContents, out var serverManifest) && !String.IsNullOrWhiteSpace(serverManifest.Name))
return await InitializeServerImportAsync(serverManifest);
if (ManifestHelper.TryDeserialize<SDK.Models.Manifest.Tool>(manifestContents, out var toolManifest))
if (ManifestHelper.TryDeserialize<SDK.Models.Manifest.Tool>(manifestContents, out var toolManifest) && !String.IsNullOrWhiteSpace(toolManifest.Name))
return await InitializeToolImportAsync(toolManifest);
throw new InvalidOperationException("Unknown manifest file");
}
}
private async Task<IEnumerable<IImportItemInfo>> InitializeByTypeAsync(ManifestType manifestType, string manifestContents)
{
switch (manifestType)
{
case ManifestType.Game:
var gameManifest = ManifestHelper.Deserialize<SDK.Models.Manifest.Game>(manifestContents);
return await InitializeGameImportAsync(gameManifest);
case ManifestType.Redistributable:
var redistributableManifest = ManifestHelper.Deserialize<SDK.Models.Manifest.Redistributable>(manifestContents);
return await InitializeRedistributableImportAsync(redistributableManifest);
case ManifestType.Server:
var serverManifest = ManifestHelper.Deserialize<SDK.Models.Manifest.Server>(manifestContents);
return await InitializeServerImportAsync(serverManifest);
case ManifestType.Tool:
var toolManifest = ManifestHelper.Deserialize<SDK.Models.Manifest.Tool>(manifestContents);
return await InitializeToolImportAsync(toolManifest);
default:
throw new InvalidOperationException($"Unsupported manifest type: {manifestType}");
}
}
public async Task InitializeMetadataUpdateAsync(SDK.Models.Manifest.Game gameManifest)
{
_developers.UseContext(this);
@ -553,17 +577,5 @@ public class ImportContext : IDisposable
{
if (Archive != null)
Archive.Dispose();
if (_uploadedArchivePath != null && File.Exists(_uploadedArchivePath))
{
try
{
File.Delete(_uploadedArchivePath);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Could not delete uploaded import archive at {Path}", _uploadedArchivePath);
}
}
}
}

View file

@ -173,7 +173,8 @@ public class ArchiveImporter(
if (archiveEntry == null)
return false;
await archiveService.WriteToFileAsync(archive, archiveEntry.OpenEntryStream());
using var entryStream = archiveEntry.OpenEntryStream();
await archiveService.WriteToFileAsync(archive, entryStream);
return true;
}

View file

@ -1,4 +1,3 @@
using AutoMapper;
using LANCommander.SDK.Enums;
using LANCommander.SDK.Models.Manifest;
using LANCommander.Server.ImportExport.Models;
@ -9,7 +8,6 @@ namespace LANCommander.Server.ImportExport.Importers;
public class RedistributableImporter(
ILogger<RedistributableImporter> logger,
IMapper mapper,
RedistributableService redistributableService,
UserService userService) : BaseImporter<Redistributable>
{
@ -28,7 +26,22 @@ public class RedistributableImporter(
public override async Task<bool> AddAsync(Redistributable record)
{
var redistributable = mapper.Map<Data.Models.Redistributable>(record);
var redistributable = new Data.Models.Redistributable
{
Id = record.Id,
Name = record.Name,
Description = record.Description,
Notes = record.Notes,
OptionSchema = record.OptionSchema,
CreatedOn = record.CreatedOn,
UpdatedOn = record.UpdatedOn,
};
if (!String.IsNullOrWhiteSpace(record.CreatedBy))
redistributable.CreatedBy = await userService.GetAsync(record.CreatedBy);
if (!String.IsNullOrWhiteSpace(record.UpdatedBy))
redistributable.UpdatedBy = await userService.GetAsync(record.UpdatedBy);
try
{

View file

@ -1,4 +1,3 @@
using AutoMapper;
using LANCommander.SDK.Enums;
using LANCommander.SDK.Models.Manifest;
using LANCommander.Server.ImportExport.Models;
@ -9,7 +8,6 @@ namespace LANCommander.Server.ImportExport.Importers;
public class ToolImporter(
ILogger<ToolImporter> logger,
IMapper mapper,
ToolService toolService,
UserService userService) : BaseImporter<Tool>
{
@ -28,7 +26,21 @@ public class ToolImporter(
public override async Task<bool> AddAsync(Tool record)
{
var tool = mapper.Map<Data.Models.Tool>(record);
var tool = new Data.Models.Tool
{
Id = record.Id,
Name = record.Name,
Description = record.Description,
Notes = record.Notes,
CreatedOn = record.CreatedOn,
UpdatedOn = record.UpdatedOn,
};
if (!String.IsNullOrWhiteSpace(record.CreatedBy))
tool.CreatedBy = await userService.GetAsync(record.CreatedBy);
if (!String.IsNullOrWhiteSpace(record.UpdatedBy))
tool.UpdatedBy = await userService.GetAsync(record.UpdatedBy);
try
{