From 0d5fbcb031d551d3ee858b3d047fcc6f5ad61a06 Mon Sep 17 00:00:00 2001
From: William Taylor <me@willtaylor.info>
Date: Fri, 8 Feb 2019 09:13:58 +0000
Subject: [PATCH] Removed primitives from services in Program.cs

This will make it easier to move dependency registration
to a system without having to new up all the services first.
Moved the primitives to an IConfiguration which is much easier to inject.
---
 .../ConfigurationOptions.cs                   | 14 ++++++
 .../Emby.Server.Implementations.csproj        |  6 +++
 .../IO/ManagedFileSystem.cs                   | 28 ++++++-----
 Jellyfin.Server/Program.cs                    | 47 +++++++++++--------
 4 files changed, 63 insertions(+), 32 deletions(-)
 create mode 100644 Emby.Server.Implementations/ConfigurationOptions.cs

diff --git a/Emby.Server.Implementations/ConfigurationOptions.cs b/Emby.Server.Implementations/ConfigurationOptions.cs
new file mode 100644
index 0000000000..0483ad207f
--- /dev/null
+++ b/Emby.Server.Implementations/ConfigurationOptions.cs
@@ -0,0 +1,14 @@
+using System.Collections.Generic;
+using Emby.Server.Implementations.IO;
+
+namespace Emby.Server.Implementations
+{
+    public static class ConfigurationOptions
+    {
+        public static readonly Dictionary<string, string> Configuration = new Dictionary<string, string>
+        {
+            {"ManagedFileSystem:DefaultDirectory", null},
+            {"ManagedFileSystem:EnableSeparateFileAndDirectoryQueries", "True"}
+        };
+    }
+}
diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
index 6bf776f533..16258c767c 100644
--- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj
+++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
@@ -46,4 +46,10 @@
     <EmbeddedResource Include="Localization\Ratings\*.csv" />
   </ItemGroup>
 
+  <ItemGroup>
+    <Reference Include="Microsoft.Extensions.Configuration.Abstractions, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60">
+      <HintPath>..\..\..\.nuget\packages\microsoft.extensions.configuration.abstractions\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.Abstractions.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+
 </Project>
diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs
index 7c44878ec2..8ffb0f74a9 100644
--- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs
+++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs
@@ -4,8 +4,10 @@ using System.Diagnostics;
 using System.IO;
 using System.Linq;
 using System.Text;
+using MediaBrowser.Common.Configuration;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.System;
+using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.Logging;
 
 namespace Emby.Server.Implementations.IO
@@ -20,30 +22,30 @@ namespace Emby.Server.Implementations.IO
         private readonly bool _supportsAsyncFileStreams;
         private char[] _invalidFileNameChars;
         private readonly List<IShortcutHandler> _shortcutHandlers = new List<IShortcutHandler>();
-        private bool EnableSeparateFileAndDirectoryQueries;
+        private readonly bool EnableSeparateFileAndDirectoryQueries;
 
-        private string _tempPath;
+        private readonly string _tempPath;
 
-        private IEnvironmentInfo _environmentInfo;
-        private bool _isEnvironmentCaseInsensitive;
+        private readonly IEnvironmentInfo _environmentInfo;
+        private readonly bool _isEnvironmentCaseInsensitive;
 
-        private string _defaultDirectory;
+        private readonly string _defaultDirectory;
 
         public ManagedFileSystem(
             ILoggerFactory loggerFactory,
             IEnvironmentInfo environmentInfo,
-            string defaultDirectory,
-            string tempPath,
-            bool enableSeparateFileAndDirectoryQueries)
+            IApplicationPaths applicationPaths,
+            IConfiguration configuration)
         {
             Logger = loggerFactory.CreateLogger("FileSystem");
             _supportsAsyncFileStreams = true;
-            _tempPath = tempPath;
+            _tempPath = applicationPaths.TempDirectory;
             _environmentInfo = environmentInfo;
-            _defaultDirectory = defaultDirectory;
+            _defaultDirectory = configuration["ManagedFileSystem:DefaultDirectory"];
 
             // On Linux with mono, this needs to be true or symbolic links are ignored
-            EnableSeparateFileAndDirectoryQueries = enableSeparateFileAndDirectoryQueries;
+            EnableSeparateFileAndDirectoryQueries =
+                bool.Parse(configuration["ManagedFileSystem:EnableSeparateFileAndDirectoryQueries"]);
 
             SetInvalidFileNameChars(environmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows);
 
@@ -718,7 +720,7 @@ namespace Emby.Server.Implementations.IO
             SetAttributes(path, false, false);
             File.Delete(path);
         }
-        
+
         public virtual List<FileSystemMetadata> GetDrives()
         {
             // Only include drives in the ready state or this method could end up being very slow, waiting for drives to timeout
@@ -790,7 +792,7 @@ namespace Emby.Server.Implementations.IO
         {
             return infos.Select(GetFileSystemMetadata);
         }
-        
+
         public virtual IEnumerable<string> GetDirectoryPaths(string path, bool recursive = false)
         {
             var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs
index ac5aab4609..7236238c2f 100644
--- a/Jellyfin.Server/Program.cs
+++ b/Jellyfin.Server/Program.cs
@@ -35,6 +35,7 @@ namespace Jellyfin.Server
         private static readonly ILoggerFactory _loggerFactory = new SerilogLoggerFactory();
         private static ILogger _logger;
         private static bool _restartOnShutdown;
+        private static IConfiguration appConfig;
 
         public static async Task Main(string[] args)
         {
@@ -78,7 +79,11 @@ namespace Jellyfin.Server
 
             // $JELLYFIN_LOG_DIR needs to be set for the logger configuration manager
             Environment.SetEnvironmentVariable("JELLYFIN_LOG_DIR", appPaths.LogDirectoryPath);
-            await CreateLogger(appPaths).ConfigureAwait(false);
+
+            appConfig = await CreateConfiguration(appPaths).ConfigureAwait(false);
+
+            await CreateLogger(appConfig, appPaths).ConfigureAwait(false);
+
             _logger = _loggerFactory.CreateLogger("Main");
 
             AppDomain.CurrentDomain.UnhandledException += (sender, e)
@@ -121,7 +126,7 @@ namespace Jellyfin.Server
             // Allow all https requests
             ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; } );
 
-            var fileSystem = new ManagedFileSystem(_loggerFactory, environmentInfo, null, appPaths.TempDirectory, true);
+            var fileSystem = new ManagedFileSystem(_loggerFactory, environmentInfo, appPaths, appConfig);
 
             using (var appHost = new CoreAppHost(
                 appPaths,
@@ -309,29 +314,33 @@ namespace Jellyfin.Server
             return new ServerApplicationPaths(dataDir, logDir, configDir, cacheDir);
         }
 
-        private static async Task CreateLogger(IApplicationPaths appPaths)
+        private static async Task<IConfiguration> CreateConfiguration(IApplicationPaths appPaths)
         {
-            try
-            {
-                string configPath = Path.Combine(appPaths.ConfigurationDirectoryPath, "logging.json");
+            string configPath = Path.Combine(appPaths.ConfigurationDirectoryPath, "logging.json");
 
-                if (!File.Exists(configPath))
+            if (!File.Exists(configPath))
+            {
+                // For some reason the csproj name is used instead of the assembly name
+                using (Stream rscstr = typeof(Program).Assembly
+                    .GetManifestResourceStream("Jellyfin.Server.Resources.Configuration.logging.json"))
+                using (Stream fstr = File.Open(configPath, FileMode.CreateNew))
                 {
-                    // For some reason the csproj name is used instead of the assembly name
-                    using (Stream rscstr = typeof(Program).Assembly
-                        .GetManifestResourceStream("Jellyfin.Server.Resources.Configuration.logging.json"))
-                    using (Stream fstr = File.Open(configPath, FileMode.CreateNew))
-                    {
-                        await rscstr.CopyToAsync(fstr).ConfigureAwait(false);
-                    }
+                    await rscstr.CopyToAsync(fstr).ConfigureAwait(false);
                 }
+            }
 
-                var configuration = new ConfigurationBuilder()
-                    .SetBasePath(appPaths.ConfigurationDirectoryPath)
-                    .AddJsonFile("logging.json")
-                    .AddEnvironmentVariables("JELLYFIN_")
-                    .Build();
+            return new ConfigurationBuilder()
+                .SetBasePath(appPaths.ConfigurationDirectoryPath)
+                .AddJsonFile("logging.json")
+                .AddEnvironmentVariables("JELLYFIN_")
+                .AddInMemoryCollection(ConfigurationOptions.Configuration)
+                .Build();
+        }
 
+        private static async Task CreateLogger(IConfiguration configuration, IApplicationPaths appPaths)
+        {
+            try
+            {
                 // Serilog.Log is used by SerilogLoggerFactory when no logger is specified
                 Serilog.Log.Logger = new LoggerConfiguration()
                     .ReadFrom.Configuration(configuration)