Unify path resolution server-wide
This commit is contained in:
parent
2ca1db535c
commit
41bcfa908d
11 changed files with 122 additions and 21 deletions
|
|
@ -189,9 +189,6 @@ namespace LANCommander.Server.Services
|
|||
{
|
||||
var storageLocation = await storageLocationService.GetAsync(storageLocationId);
|
||||
|
||||
if (!Directory.Exists(storageLocation.Path))
|
||||
Directory.CreateDirectory(storageLocation.Path);
|
||||
|
||||
var archive = new Archive
|
||||
{
|
||||
ObjectKey = Guid.NewGuid().ToString(),
|
||||
|
|
|
|||
|
|
@ -67,6 +67,8 @@ namespace LANCommander.Server.Services
|
|||
});
|
||||
}
|
||||
|
||||
storagePath = AppPaths.ResolveStorageLocationPath(storagePath);
|
||||
|
||||
if (!Directory.Exists(storagePath))
|
||||
Directory.CreateDirectory(storagePath);
|
||||
|
||||
|
|
|
|||
|
|
@ -136,6 +136,8 @@ namespace LANCommander.Server.Services
|
|||
});
|
||||
}
|
||||
|
||||
storagePath = AppPaths.ResolveStorageLocationPath(storagePath);
|
||||
|
||||
if (!Directory.Exists(storagePath))
|
||||
Directory.CreateDirectory(storagePath);
|
||||
|
||||
|
|
|
|||
|
|
@ -140,8 +140,11 @@ namespace LANCommander.Server.Services
|
|||
|
||||
foreach (var storageLocation in storageLocations)
|
||||
{
|
||||
if (!Directory.Exists(storageLocation.Path))
|
||||
Directory.CreateDirectory(storageLocation.Path);
|
||||
// Store the configured (possibly relative) path, but create the resolved physical directory.
|
||||
var resolvedPath = AppPaths.ResolveStorageLocationPath(storageLocation.Path);
|
||||
|
||||
if (!Directory.Exists(resolvedPath))
|
||||
Directory.CreateDirectory(resolvedPath);
|
||||
|
||||
try
|
||||
{
|
||||
|
|
|
|||
|
|
@ -42,8 +42,9 @@ namespace LANCommander.Server.Services
|
|||
public IEnumerable<LauncherArtifact> GetLauncherArtifactsFromLocalFiles()
|
||||
{
|
||||
var currentVersion = versionProvider.GetCurrentVersion();
|
||||
var downloadedLaunchers = Directory.GetFiles(_settingsProvider.CurrentValue.Server.Launcher.StoragePath, $"LANCommander.Launcher*v{currentVersion.WithoutMetadata()}.*");
|
||||
var downloadedInstallers = Directory.GetFiles(_settingsProvider.CurrentValue.Server.Launcher.StoragePath, $"LANCommander.Launcher-{currentVersion.WithoutMetadata()}*Setup*.*");
|
||||
var launcherStoragePath = AppPaths.ResolveStorageLocationPath(_settingsProvider.CurrentValue.Server.Launcher.StoragePath);
|
||||
var downloadedLaunchers = Directory.GetFiles(launcherStoragePath, $"LANCommander.Launcher*v{currentVersion.WithoutMetadata()}.*");
|
||||
var downloadedInstallers = Directory.GetFiles(launcherStoragePath, $"LANCommander.Launcher-{currentVersion.WithoutMetadata()}*Setup*.*");
|
||||
|
||||
var downloads = downloadedLaunchers.Concat(downloadedInstallers).Distinct();
|
||||
|
||||
|
|
@ -149,7 +150,7 @@ namespace LANCommander.Server.Services
|
|||
client.DownloadFileCompleted += ReleaseDownloaded;
|
||||
client.QueryString.Add("Version", release.TagName);
|
||||
|
||||
await client.DownloadFileTaskAsync(new Uri(releaseFile), Path.Combine(_settingsProvider.CurrentValue.Server.Update.StoragePath, $"{release.TagName}.zip"));
|
||||
await client.DownloadFileTaskAsync(new Uri(releaseFile), AppPaths.ResolveStorageLocationPath(_settingsProvider.CurrentValue.Server.Update.StoragePath, $"{release.TagName}.zip"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -181,7 +182,7 @@ namespace LANCommander.Server.Services
|
|||
var uri = new Uri(releaseFile);
|
||||
|
||||
client.QueryString.Add("Version", release.TagName);
|
||||
await client.DownloadFileTaskAsync(uri, Path.Combine(_settingsProvider.CurrentValue.Server.Update.StoragePath, $"{release.TagName}.zip"));
|
||||
await client.DownloadFileTaskAsync(uri, AppPaths.ResolveStorageLocationPath(_settingsProvider.CurrentValue.Server.Update.StoragePath, $"{release.TagName}.zip"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -216,7 +217,7 @@ namespace LANCommander.Server.Services
|
|||
private void ReleaseDownloaded(object? sender, System.ComponentModel.AsyncCompletedEventArgs e)
|
||||
{
|
||||
string version = ((WebClient)sender).QueryString["Version"];
|
||||
string path = Path.Combine(_settingsProvider.CurrentValue.Server.Update.StoragePath, $"{version}.zip");
|
||||
string path = AppPaths.ResolveStorageLocationPath(_settingsProvider.CurrentValue.Server.Update.StoragePath, $"{version}.zip");
|
||||
|
||||
_logger?.LogInformation("Update version {Version} has been downloaded", version);
|
||||
|
||||
|
|
@ -242,7 +243,7 @@ namespace LANCommander.Server.Services
|
|||
var process = new ProcessStartInfo();
|
||||
|
||||
process.FileName = processExecutable;
|
||||
process.Arguments = $"-Version {version} -Path \"{_settingsProvider.CurrentValue.Server.Update.StoragePath}\" -Executable {Process.GetCurrentProcess().MainModule.FileName}";
|
||||
process.Arguments = $"-Version {version} -Path \"{AppPaths.ResolveStorageLocationPath(_settingsProvider.CurrentValue.Server.Update.StoragePath)}\" -Executable {Process.GetCurrentProcess().MainModule.FileName}";
|
||||
process.UseShellExecute = true;
|
||||
|
||||
Process.Start(process);
|
||||
|
|
@ -260,7 +261,7 @@ namespace LANCommander.Server.Services
|
|||
|
||||
public LauncherArtifact GetLauncherArtifact(string objectKey)
|
||||
{
|
||||
string name = Path.Combine(_settingsProvider.CurrentValue.Server.Launcher.StoragePath, objectKey);
|
||||
string name = AppPaths.ResolveStorageLocationPath(_settingsProvider.CurrentValue.Server.Launcher.StoragePath, objectKey);
|
||||
return GetArtifactFromName(name);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using LANCommander.SDK;
|
||||
using LANCommander.SDK.Models;
|
||||
using LANCommander.Server.Services;
|
||||
using LANCommander.Server.Services.Abstractions;
|
||||
|
|
@ -23,7 +24,7 @@ public static class LauncherEndpoints
|
|||
{
|
||||
var version = versionProvider.GetCurrentVersion();
|
||||
var fileName = $"LANCommander.Launcher-Windows-x64-v{version.WithoutMetadata()}.zip";
|
||||
var path = Path.Combine(settingsProvider.CurrentValue.Server.Launcher.StoragePath, fileName);
|
||||
var path = AppPaths.ResolveStorageLocationPath(settingsProvider.CurrentValue.Server.Launcher.StoragePath, fileName);
|
||||
|
||||
if (!File.Exists(path) || !settingsProvider.CurrentValue.Server.Launcher.HostUpdates)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -28,9 +28,6 @@ public static class UploadEndpoints
|
|||
storageLocationId == null || storageLocationId == Guid.Empty ? null : storageLocationId,
|
||||
SDK.Enums.StorageLocationType.Archive);
|
||||
|
||||
if (!Directory.Exists(storageLocation.Path))
|
||||
Directory.CreateDirectory(storageLocation.Path);
|
||||
|
||||
var archive = new Archive
|
||||
{
|
||||
ObjectKey = Guid.NewGuid().ToString(),
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using LANCommander.SDK.Extensions;
|
||||
using LANCommander.SDK;
|
||||
using LANCommander.SDK.Extensions;
|
||||
using LANCommander.Server.Services;
|
||||
using LANCommander.Server.Services.Models;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
|
@ -28,7 +29,7 @@ namespace LANCommander.Server.Jobs.Background
|
|||
if (!localArtifacts.Any(a => a.Name.EndsWith(artifact.Name)))
|
||||
{
|
||||
using (var downloadStream = await httpClient.GetStreamAsync(artifact.Url))
|
||||
using (var fs = new FileStream(Path.Combine(settings.Value.Server.Launcher.StoragePath, artifact.Name), FileMode.Create))
|
||||
using (var fs = new FileStream(AppPaths.ResolveStorageLocationPath(settings.Value.Server.Launcher.StoragePath, artifact.Name), FileMode.Create))
|
||||
{
|
||||
await downloadStream.CopyToAsync(fs);
|
||||
op.Complete();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,89 @@
|
|||
using LANCommander.SDK;
|
||||
using LANCommander.SDK.Helpers;
|
||||
using LANCommander.SDK.Migrations;
|
||||
using Semver;
|
||||
|
||||
namespace LANCommander.Server.Migrations;
|
||||
|
||||
/// <summary>
|
||||
/// Moves the settings-based storage directories (Update, Launcher, Backups, Snippets, Modules) from
|
||||
/// their previously-written raw locations (resolved verbatim relative to the working directory) to the
|
||||
/// unified location produced by <see cref="AppPaths.ResolveStorageLocationPath(string, string[])"/>.
|
||||
/// This aligns runtime writes with the same resolution rule used everywhere else so relative paths land
|
||||
/// under the config directory instead of next to the binary.
|
||||
/// </summary>
|
||||
public class AlignSettingsStoragePathsMigration(
|
||||
SettingsProvider<Settings.Settings> settingsProvider,
|
||||
ILogger<AlignSettingsStoragePathsMigration> logger) : FileSystemMigration(logger)
|
||||
{
|
||||
public override SemVersion Version => new(2, 1, 0);
|
||||
|
||||
private IEnumerable<string> GetConfiguredPaths()
|
||||
{
|
||||
var settings = settingsProvider.CurrentValue;
|
||||
|
||||
yield return settings.Server.Update.StoragePath;
|
||||
yield return settings.Server.Launcher.StoragePath;
|
||||
yield return settings.Server.Backups.StoragePath;
|
||||
yield return settings.Server.Scripts.Snippets.StoragePath;
|
||||
yield return settings.Server.Scripts.Modules.StoragePath;
|
||||
}
|
||||
|
||||
private static (string Source, string Destination)? GetMove(string configuredPath)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(configuredPath))
|
||||
return null;
|
||||
|
||||
// Rooted paths already resolve verbatim, so there is nothing to move.
|
||||
if (Path.IsPathRooted(configuredPath))
|
||||
return null;
|
||||
|
||||
var source = Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), configuredPath));
|
||||
var destination = AppPaths.ResolveStorageLocationPath(configuredPath);
|
||||
|
||||
if (string.Equals(source, destination, StringComparison.Ordinal))
|
||||
return null;
|
||||
|
||||
return (source, destination);
|
||||
}
|
||||
|
||||
public override async Task ExecuteAsync()
|
||||
{
|
||||
foreach (var configuredPath in GetConfiguredPaths())
|
||||
{
|
||||
var move = GetMove(configuredPath);
|
||||
|
||||
if (move == null)
|
||||
continue;
|
||||
|
||||
var (source, destination) = move.Value;
|
||||
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(source))
|
||||
continue;
|
||||
|
||||
Logger.LogInformation("Moving storage directory from \"{Source}\" to \"{Destination}\"", source, destination);
|
||||
|
||||
DirectoryHelper.MoveContents(source, destination);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Error while moving storage directory from \"{Source}\" to \"{Destination}\"", source, destination);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override Task<bool> ShouldExecuteAsync()
|
||||
{
|
||||
foreach (var configuredPath in GetConfiguredPaths())
|
||||
{
|
||||
var move = GetMove(configuredPath);
|
||||
|
||||
if (move != null && Directory.Exists(move.Value.Source))
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
}
|
||||
|
|
@ -23,9 +23,14 @@ public static class Filesystem
|
|||
|
||||
foreach (var directory in directories)
|
||||
{
|
||||
logger.LogDebug("Ensuring directory {Directory} exists", directory);
|
||||
if (!Directory.Exists(directory))
|
||||
Directory.CreateDirectory(directory);
|
||||
if (string.IsNullOrWhiteSpace(directory))
|
||||
continue;
|
||||
|
||||
var resolved = AppPaths.ResolveStorageLocationPath(directory);
|
||||
|
||||
logger.LogDebug("Ensuring directory {Directory} exists", resolved);
|
||||
if (!Directory.Exists(resolved))
|
||||
Directory.CreateDirectory(resolved);
|
||||
}
|
||||
|
||||
return app;
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@ public static class Migrations
|
|||
builder.Services.AddScoped<IMigration, MoveLauncherMigration>();
|
||||
builder.Services.AddScoped<IMigration, MoveLogsMigration>();
|
||||
|
||||
// Align settings-based storage paths with the unified resolver
|
||||
builder.Services.AddScoped<IMigration, AlignSettingsStoragePathsMigration>();
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue