diff --git a/build/Version.props b/build/Version.props
index 7178bdfc80..d37c328cda 100644
--- a/build/Version.props
+++ b/build/Version.props
@@ -3,7 +3,7 @@
- 5.13.6
+ 5.13.7
4.7.1
9.11.0
6.0.0
diff --git a/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs b/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs
index 1b74ccfe08..087503d68c 100644
--- a/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs
+++ b/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs
@@ -236,7 +236,7 @@ namespace Tgstation.Server.Host.Components.StaticFiles
}
///
- public async Task> ListDirectory(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken)
+ public async Task> ListDirectory(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken)
{
await EnsureDirectories(cancellationToken);
var path = ValidateConfigRelativePath(configurationRelativePath);
@@ -252,14 +252,14 @@ namespace Tgstation.Server.Host.Components.StaticFiles
{
IsDirectory = true,
Path = ioManager.ConcatPath(configurationRelativePath, x),
- }).OrderBy(file => file.Path));
+ }));
enumerator = synchronousIOManager.GetFiles(path, cancellationToken);
result.AddRange(enumerator.Select(x => new ConfigurationFileResponse
{
IsDirectory = false,
Path = ioManager.ConcatPath(configurationRelativePath, x),
- }).OrderBy(file => file.Path));
+ }));
}
using (SemaphoreSlimContext.TryLock(semaphore, out var locked))
@@ -276,7 +276,10 @@ namespace Tgstation.Server.Host.Components.StaticFiles
await systemIdentity.RunImpersonated(ListImpl, cancellationToken);
}
- return result;
+ return result
+ .AsQueryable()
+ .OrderBy(configFile => !configFile.IsDirectory)
+ .ThenBy(configFile => configFile.Path);
}
///
diff --git a/src/Tgstation.Server.Host/Components/StaticFiles/IConfiguration.cs b/src/Tgstation.Server.Host/Components/StaticFiles/IConfiguration.cs
index 4fece676c9..b4ed9f59f9 100644
--- a/src/Tgstation.Server.Host/Components/StaticFiles/IConfiguration.cs
+++ b/src/Tgstation.Server.Host/Components/StaticFiles/IConfiguration.cs
@@ -1,5 +1,5 @@
using System;
-using System.Collections.Generic;
+using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -38,8 +38,8 @@ namespace Tgstation.Server.Host.Components.StaticFiles
/// The relative path in the Configuration directory.
/// The for the operation. If , the operation will be performed as the user of the .
/// The for the operation.
- /// A resulting in the s for the items in the directory. and will both be . will be returned if the operation failed due to access contention.
- Task> ListDirectory(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken);
+ /// A resulting in an of the s for the items in the directory. and will both be . will be returned if the operation failed due to access contention.
+ Task> ListDirectory(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken);
///
/// Reads a given .
diff --git a/src/Tgstation.Server.Host/Controllers/ConfigurationController.cs b/src/Tgstation.Server.Host/Controllers/ConfigurationController.cs
index 1a7e2dab49..6be4c6df5f 100644
--- a/src/Tgstation.Server.Host/Controllers/ConfigurationController.cs
+++ b/src/Tgstation.Server.Host/Controllers/ConfigurationController.cs
@@ -1,6 +1,5 @@
using System;
using System.IO;
-using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -190,10 +189,7 @@ namespace Tgstation.Server.Host.Controllers
return new PaginatableResult(
Conflict(new ErrorMessageResponse(ErrorCode.ConfigurationContendedAccess)));
- return new PaginatableResult(
- result
- .AsQueryable()
- .OrderBy(x => x)); // ordering performed by IConfiguration
+ return new PaginatableResult(result);
}
catch (NotImplementedException ex)
{
diff --git a/tests/Tgstation.Server.Host.Tests/Components/StaticFiles/TestConfiguration.cs b/tests/Tgstation.Server.Host.Tests/Components/StaticFiles/TestConfiguration.cs
index cec38f9875..68241988d1 100644
--- a/tests/Tgstation.Server.Host.Tests/Components/StaticFiles/TestConfiguration.cs
+++ b/tests/Tgstation.Server.Host.Tests/Components/StaticFiles/TestConfiguration.cs
@@ -1,5 +1,6 @@
using System;
using System.IO;
+using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -57,7 +58,7 @@ namespace Tgstation.Server.Host.Components.StaticFiles.Tests
await configuration.StartAsync(CancellationToken.None);
- var listResponse = await configuration.ListDirectory(".", null, CancellationToken.None);
+ var listResponse = (await configuration.ListDirectory(".", null, CancellationToken.None)).ToList();
Assert.AreEqual(9, listResponse.Count);
Assert.AreEqual("a", listResponse[0].Path[2..]);
Assert.AreEqual("c", listResponse[1].Path[2..]);
@@ -76,7 +77,7 @@ namespace Tgstation.Server.Host.Components.StaticFiles.Tests
await ioManager.WriteAllBytes("GameStaticFiles/config/unbuyableshuttles.txt", Array.Empty(), CancellationToken.None);
await ioManager.WriteAllBytes("GameStaticFiles/config/spaceruinblacklist.txt", Array.Empty(), CancellationToken.None);
- listResponse = await configuration.ListDirectory("GameStaticFiles/config", null, CancellationToken.None);
+ listResponse = (await configuration.ListDirectory("GameStaticFiles/config", null, CancellationToken.None)).ToList();
var substringStart = "GameStaticFiles/config".Length + 1;
Assert.AreEqual(6, listResponse.Count);
Assert.AreEqual("title_music", listResponse[0].Path[substringStart..]);
diff --git a/tests/Tgstation.Server.Tests/Live/Instance/ConfigurationTest.cs b/tests/Tgstation.Server.Tests/Live/Instance/ConfigurationTest.cs
index c921b2c9cd..1008406cd7 100644
--- a/tests/Tgstation.Server.Tests/Live/Instance/ConfigurationTest.cs
+++ b/tests/Tgstation.Server.Tests/Live/Instance/ConfigurationTest.cs
@@ -1,9 +1,6 @@
using System;
using System.IO;
using System.Linq;
-using System.Net.Http;
-using System.Net.Mime;
-using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
@@ -14,9 +11,7 @@ using Tgstation.Server.Api.Models;
using Tgstation.Server.Api.Models.Request;
using Tgstation.Server.Client;
using Tgstation.Server.Client.Components;
-using Tgstation.Server.Common;
using Tgstation.Server.Host.IO;
-using Tgstation.Server.Host.System;
namespace Tgstation.Server.Tests.Live.Instance
{
@@ -139,12 +134,49 @@ namespace Tgstation.Server.Tests.Live.Instance
TaskCreationOptions.LongRunning,
TaskScheduler.Current);
- public Task RunPreWatchdog(CancellationToken cancellationToken)
+ async Task TestListing(CancellationToken cancellationToken)
{
- return Task.WhenAll(
- TestUploadDownloadAndDeleteDirectory(cancellationToken),
- SetupDMApiTests(cancellationToken),
- TestPregeneratedFilesExist(cancellationToken));
+ await using var uploadMs = new MemoryStream(Encoding.UTF8.GetBytes("Hello world!"));
+ await configurationClient.Write(
+ new ConfigurationFileRequest
+ {
+ Path = "f-TestFile.txt"
+ },
+ uploadMs,
+ cancellationToken);
+ uploadMs.Seek(0, SeekOrigin.Begin);
+ await configurationClient.Write(
+ new ConfigurationFileRequest
+ {
+ Path = "f-TestDir/f-TestFile.txt"
+ },
+ uploadMs,
+ cancellationToken);
+
+ var baseList = await configurationClient.List(null, ".", cancellationToken);
+ Assert.AreEqual(5, baseList.Count);
+
+ Assert.AreEqual($"/CodeModifications", baseList[0].Path);
+ Assert.IsTrue(baseList[0].IsDirectory);
+ Assert.AreEqual($"/EventScripts", baseList[1].Path);
+ Assert.IsTrue(baseList[1].IsDirectory);
+ Assert.AreEqual($"/f-TestDir", baseList[2].Path);
+ Assert.IsTrue(baseList[2].IsDirectory);
+ Assert.AreEqual($"/GameStaticFiles", baseList[3].Path);
+ Assert.IsTrue(baseList[3].IsDirectory);
+ Assert.AreEqual($"/f-TestFile.txt", baseList[4].Path);
+ Assert.IsFalse(baseList[4].IsDirectory);
}
+
+ async Task SequencedApiTests(CancellationToken cancellationToken)
+ {
+ await TestUploadDownloadAndDeleteDirectory(cancellationToken);
+ await TestListing(cancellationToken);
+ }
+
+ public Task RunPreWatchdog(CancellationToken cancellationToken) => Task.WhenAll(
+ SequencedApiTests(cancellationToken),
+ SetupDMApiTests(cancellationToken),
+ TestPregeneratedFilesExist(cancellationToken));
}
}