Просмотр исходного кода

Enable nullable reference types for Jellyfin.Server

Bond_009 5 лет назад
Родитель
Сommit
2702dca8b6

+ 1 - 2
Jellyfin.Server/Jellyfin.Server.csproj

@@ -9,9 +9,8 @@
   </PropertyGroup>
 
   <PropertyGroup>
-    <!-- We need at least C# 7.1 for async main-->
-    <LangVersion>latest</LangVersion>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+    <Nullable>enable</Nullable>
   </PropertyGroup>
 
   <ItemGroup>

+ 26 - 8
Jellyfin.Server/Program.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Diagnostics;
+using System.Globalization;
 using System.IO;
 using System.Linq;
 using System.Net;
@@ -21,6 +22,7 @@ using MediaBrowser.Model.Globalization;
 using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
 using Serilog;
 using Serilog.Extensions.Logging;
 using SQLitePCL;
@@ -35,7 +37,7 @@ namespace Jellyfin.Server
     {
         private static readonly CancellationTokenSource _tokenSource = new CancellationTokenSource();
         private static readonly ILoggerFactory _loggerFactory = new SerilogLoggerFactory();
-        private static ILogger _logger;
+        private static ILogger _logger = NullLogger.Instance;
         private static bool _restartOnShutdown;
 
         /// <summary>
@@ -86,6 +88,12 @@ namespace Jellyfin.Server
         {
             var stopWatch = new Stopwatch();
             stopWatch.Start();
+
+            // Log all uncaught exception to std error
+            static void UnhandledExceptionToConsole(object sender, UnhandledExceptionEventArgs e) =>
+                Console.Error.WriteLine("Unhandled Exception\n" + e.ExceptionObject.ToString());
+            AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionToConsole;
+
             ServerApplicationPaths appPaths = CreateApplicationPaths(options);
 
             // $JELLYFIN_LOG_DIR needs to be set for the logger configuration manager
@@ -97,6 +105,8 @@ namespace Jellyfin.Server
 
             _logger = _loggerFactory.CreateLogger("Main");
 
+            // Log uncaught exceptions to the logging instead of std error
+            AppDomain.CurrentDomain.UnhandledException -= UnhandledExceptionToConsole;
             AppDomain.CurrentDomain.UnhandledException += (sender, e)
                 => _logger.LogCritical((Exception)e.ExceptionObject, "Unhandled Exception");
 
@@ -129,7 +139,7 @@ namespace Jellyfin.Server
 
             _logger.LogInformation(
                 "Jellyfin version: {Version}",
-                Assembly.GetEntryAssembly().GetName().Version.ToString(3));
+                Assembly.GetEntryAssembly()!.GetName().Version!.ToString(3));
 
             ApplicationHost.LogEnvironmentInfo(_logger, appPaths);
 
@@ -361,16 +371,25 @@ namespace Jellyfin.Server
 
         private static async Task<IConfiguration> CreateConfiguration(IApplicationPaths appPaths)
         {
+            const string ResourcePath = "Jellyfin.Server.Resources.Configuration.logging.json";
             string configPath = Path.Combine(appPaths.ConfigurationDirectoryPath, "logging.json");
 
             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))
+                using (Stream? resource = typeof(Program).Assembly.GetManifestResourceStream(ResourcePath))
                 {
-                    await rscstr.CopyToAsync(fstr).ConfigureAwait(false);
+                    if (resource == null)
+                    {
+                        throw new InvalidOperationException(
+                            string.Format(
+                                CultureInfo.InvariantCulture,
+                                "Invalid resource path: '{0}'",
+                                ResourcePath));
+                    }
+
+                    using Stream dst = File.Open(configPath, FileMode.CreateNew);
+                    await resource.CopyToAsync(dst).ConfigureAwait(false);
                 }
             }
 
@@ -433,7 +452,7 @@ namespace Jellyfin.Server
         {
             _logger.LogInformation("Starting new instance");
 
-            string module = options.RestartPath;
+            var module = options.RestartPath;
 
             if (string.IsNullOrWhiteSpace(module))
             {
@@ -441,7 +460,6 @@ namespace Jellyfin.Server
             }
 
             string commandLineArgsString;
-
             if (options.RestartArgs != null)
             {
                 commandLineArgsString = options.RestartArgs ?? string.Empty;

+ 9 - 9
Jellyfin.Server/StartupOptions.cs

@@ -13,39 +13,39 @@ namespace Jellyfin.Server
         /// </summary>
         /// <value>The path to the data directory.</value>
         [Option('d', "datadir", Required = false, HelpText = "Path to use for the data folder (database files, etc.).")]
-        public string DataDir { get; set; }
+        public string? DataDir { get; set; }
 
         /// <summary>
         /// Gets or sets the path to the web directory.
         /// </summary>
         /// <value>The path to the web directory.</value>
         [Option('w', "webdir", Required = false, HelpText = "Path to the Jellyfin web UI resources.")]
-        public string WebDir { get; set; }
+        public string? WebDir { get; set; }
 
         /// <summary>
         /// Gets or sets the path to the cache directory.
         /// </summary>
         /// <value>The path to the cache directory.</value>
         [Option('C', "cachedir", Required = false, HelpText = "Path to use for caching.")]
-        public string CacheDir { get; set; }
+        public string? CacheDir { get; set; }
 
         /// <summary>
         /// Gets or sets the path to the config directory.
         /// </summary>
         /// <value>The path to the config directory.</value>
         [Option('c', "configdir", Required = false, HelpText = "Path to use for configuration data (user settings and pictures).")]
-        public string ConfigDir { get; set; }
+        public string? ConfigDir { get; set; }
 
         /// <summary>
         /// Gets or sets the path to the log directory.
         /// </summary>
         /// <value>The path to the log directory.</value>
         [Option('l', "logdir", Required = false, HelpText = "Path to use for writing log files.")]
-        public string LogDir { get; set; }
+        public string? LogDir { get; set; }
 
         /// <inheritdoc />
         [Option("ffmpeg", Required = false, HelpText = "Path to external FFmpeg executable to use in place of default found in PATH.")]
-        public string FFmpegPath { get; set; }
+        public string? FFmpegPath { get; set; }
 
         /// <inheritdoc />
         [Option("service", Required = false, HelpText = "Run as headless service.")]
@@ -57,14 +57,14 @@ namespace Jellyfin.Server
 
         /// <inheritdoc />
         [Option("package-name", Required = false, HelpText = "Used when packaging Jellyfin (example, synology).")]
-        public string PackageName { get; set; }
+        public string? PackageName { get; set; }
 
         /// <inheritdoc />
         [Option("restartpath", Required = false, HelpText = "Path to restart script.")]
-        public string RestartPath { get; set; }
+        public string? RestartPath { get; set; }
 
         /// <inheritdoc />
         [Option("restartargs", Required = false, HelpText = "Arguments for restart script.")]
-        public string RestartArgs { get; set; }
+        public string? RestartArgs { get; set; }
     }
 }

+ 2 - 0
jellyfin.ruleset

@@ -6,6 +6,8 @@
     <!-- disable warning SA1204: Static members must appear before non-static members -->
     <Rule Id="SA1204" Action="Info" />
 
+    <!-- disable warning SA1009: Closing parenthesis should be followed by a space. -->
+    <Rule Id="SA1009" Action="None" />
     <!-- disable warning SA1101: Prefix local calls with 'this.' -->
     <Rule Id="SA1101" Action="None" />
     <!-- disable warning SA1108: Block statements should not contain embedded comments -->