From 485a3ce47bcf0a0c5c4fa22068b2911dd46cae96 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Thu, 11 Oct 2018 11:54:01 -0400 Subject: [PATCH 1/4] Ensure .tgsignore always exists --- .../Components/StaticFiles/Configuration.cs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs b/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs index de3f3877c8..ca60bd038a 100644 --- a/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs +++ b/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs @@ -22,6 +22,11 @@ namespace Tgstation.Server.Host.Components.StaticFiles const string EventScriptsSubdirectory = "EventScripts"; const string GameStaticFilesSubdirectory = "GameStaticFiles"; + /// + /// Name of the ignore file in + /// + const string StaticIgnoreFile = ".tgsignore"; + const string CodeModificationsHeadFile = "HeadInclude.dm"; const string CodeModificationsTailFile = "TailInclude.dm"; @@ -98,7 +103,18 @@ namespace Tgstation.Server.Host.Components.StaticFiles /// /// The for the operation /// A representing the running operation - Task EnsureDirectories(CancellationToken cancellationToken) => Task.WhenAll(ioManager.CreateDirectory(CodeModificationsSubdirectory, cancellationToken), ioManager.CreateDirectory(EventScriptsSubdirectory, cancellationToken), ioManager.CreateDirectory(GameStaticFilesSubdirectory, cancellationToken)); + async Task EnsureDirectories(CancellationToken cancellationToken) + { + async Task ValidateStaticFolder() + { + await ioManager.CreateDirectory(GameStaticFilesSubdirectory, cancellationToken).ConfigureAwait(false); + var staticIgnorePath = ioManager.ConcatPath(GameStaticFilesSubdirectory, StaticIgnoreFile); + if(!await ioManager.FileExists(staticIgnorePath, cancellationToken).ConfigureAwait(false)) + await ioManager.WriteAllBytes(staticIgnorePath, Array.Empty(), cancellationToken).ConfigureAwait(false); + } + + await Task.WhenAll(ioManager.CreateDirectory(CodeModificationsSubdirectory, cancellationToken), ioManager.CreateDirectory(EventScriptsSubdirectory, cancellationToken), ValidateStaticFolder()).ConfigureAwait(false); + } /// public async Task CopyDMFilesTo(string dmeFile, string destination, CancellationToken cancellationToken) From ecbdfd3a09f8ccc11e41f92ab819c0f2def113b1 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Thu, 11 Oct 2018 12:08:35 -0400 Subject: [PATCH 2/4] Fix Windows byond installer version comparison --- .../Components/Byond/WindowsByondInstaller.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Tgstation.Server.Host/Components/Byond/WindowsByondInstaller.cs b/src/Tgstation.Server.Host/Components/Byond/WindowsByondInstaller.cs index 8687d24615..c3f051fa60 100644 --- a/src/Tgstation.Server.Host/Components/Byond/WindowsByondInstaller.cs +++ b/src/Tgstation.Server.Host/Components/Byond/WindowsByondInstaller.cs @@ -124,7 +124,7 @@ namespace Tgstation.Server.Host.Components.Byond //after this version lummox made DD depend of directx lol //but then he became amazing and not only fixed it but also gave us 30s compiles \[T]/ - if (version.Major == 512 && version.Minor >= 1427 && version.Major < 1452 && !installedDirectX) + if (version.Major == 512 && version.Minor >= 1427 && version.Minor < 1452 && !installedDirectX) using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false)) //check again because race conditions if (!installedDirectX) From 3909e5c2f7b90e0825d67d3d9487ac8ee99e6d47 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Thu, 11 Oct 2018 12:25:49 -0400 Subject: [PATCH 3/4] Implement static file ignoring --- .../Components/StaticFiles/Configuration.cs | 47 ++++++++++++++++++- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs b/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs index ca60bd038a..52bcd6b398 100644 --- a/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs +++ b/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs @@ -6,6 +6,7 @@ using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Security.Cryptography; +using System.Text; using System.Threading; using System.Threading.Tasks; using Tgstation.Server.Api.Models; @@ -98,6 +99,12 @@ namespace Tgstation.Server.Host.Components.StaticFiles /// public void Dispose() => semaphore.Dispose(); + /// + /// Get the proper path to + /// + /// The relative path to + string StaticIgnorePath() => ioManager.ConcatPath(GameStaticFilesSubdirectory, StaticIgnoreFile); + /// /// Ensures standard configuration directories exist /// @@ -108,7 +115,7 @@ namespace Tgstation.Server.Host.Components.StaticFiles async Task ValidateStaticFolder() { await ioManager.CreateDirectory(GameStaticFilesSubdirectory, cancellationToken).ConfigureAwait(false); - var staticIgnorePath = ioManager.ConcatPath(GameStaticFilesSubdirectory, StaticIgnoreFile); + var staticIgnorePath = StaticIgnorePath(); if(!await ioManager.FileExists(staticIgnorePath, cancellationToken).ConfigureAwait(false)) await ioManager.WriteAllBytes(staticIgnorePath, Array.Empty(), cancellationToken).ConfigureAwait(false); } @@ -270,6 +277,26 @@ namespace Tgstation.Server.Host.Components.StaticFiles /// public async Task SymlinkStaticFilesTo(string destination, CancellationToken cancellationToken) { + async Task> GetIgnoreFiles() + { + var ignoreFileBytes = await ioManager.ReadAllBytes(StaticIgnorePath(), cancellationToken).ConfigureAwait(false); + var ignoreFileText = Encoding.UTF8.GetString(ignoreFileBytes); + + //we don't want to lose trailing whitespace on linux + + var results = new List { StaticIgnoreFile }; + using (var reader = new StringReader(ignoreFileText)) { + cancellationToken.ThrowIfCancellationRequested(); + var line = await reader.ReadLineAsync().ConfigureAwait(false); + if (!String.IsNullOrEmpty(line)) + results.Add(line); + } + + return results; + }; + + IReadOnlyList ignoreFiles; + async Task SymlinkBase(bool files) { Task> task; @@ -281,7 +308,22 @@ namespace Tgstation.Server.Host.Components.StaticFiles await Task.WhenAll(task.Result.Select(async x => { - var destPath = ioManager.ConcatPath(destination, ioManager.GetFileName(x)); + var fileName = ioManager.GetFileName(x); + + bool ignored; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + //need to normalize + ignored = ignoreFiles.Any(y => fileName.ToUpperInvariant() == y.ToUpperInvariant()); + else + ignored = ignoreFiles.Any(y => fileName == y); + + if (ignored) + { + logger.LogTrace("Ignoring static file {0}...", fileName); + return; + } + + var destPath = ioManager.ConcatPath(destination, fileName); logger.LogTrace("Symlinking {0} to {1}...", x, destPath); var fileExistsTask = ioManager.FileExists(destPath, cancellationToken); if (await ioManager.DirectoryExists(destPath, cancellationToken).ConfigureAwait(false)) @@ -296,6 +338,7 @@ namespace Tgstation.Server.Host.Components.StaticFiles using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false)) { await EnsureDirectories(cancellationToken).ConfigureAwait(false); + ignoreFiles = await GetIgnoreFiles().ConfigureAwait(false); await Task.WhenAll(SymlinkBase(true), SymlinkBase(false)).ConfigureAwait(false); } } From a6e04368e434f498ee2444ba858e9834d461f6d9 Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Thu, 11 Oct 2018 12:26:03 -0400 Subject: [PATCH 4/4] Document static file ignoring --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 47bcb00689..29eb729a7f 100644 --- a/README.md +++ b/README.md @@ -315,7 +315,7 @@ This folder can contain anything. But, when certain events occur in the instance #### GameStaticFiles -Any files and folders contained in this root level of this folder will be symbolically linked to all deployments at the time they are created. This allows persistent game data (BYOND `.sav`s or code configuration files for example) to persist across all deployments. +Any files and folders contained in this root level of this folder will be symbolically linked to all deployments at the time they are created. This allows persistent game data (BYOND `.sav`s or code configuration files for example) to persist across all deployments. This folder contains a .tgsignore file which can be used to prevent symlinks from being generated by entering the names of files and folders (1 per line) ### Updating