mirror of
				https://github.com/jellyfin/jellyfin.git
				synced 2025-11-04 03:27:21 -05:00 
			
		
		
		
	Merge pull request #1942 from Bond-009/nullable
Enable nullable reference types for Jellyfin.Server
This commit is contained in:
		
						commit
						c45d54efb2
					
				@ -10,6 +10,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  <PropertyGroup>
 | 
					  <PropertyGroup>
 | 
				
			||||||
    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
 | 
					    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
 | 
				
			||||||
 | 
					    <Nullable>enable</Nullable>
 | 
				
			||||||
  </PropertyGroup>
 | 
					  </PropertyGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <ItemGroup>
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,6 @@
 | 
				
			|||||||
using System;
 | 
					using System;
 | 
				
			||||||
using System.Diagnostics;
 | 
					using System.Diagnostics;
 | 
				
			||||||
 | 
					using System.Globalization;
 | 
				
			||||||
using System.IO;
 | 
					using System.IO;
 | 
				
			||||||
using System.Linq;
 | 
					using System.Linq;
 | 
				
			||||||
using System.Net;
 | 
					using System.Net;
 | 
				
			||||||
@ -21,6 +22,7 @@ using MediaBrowser.Model.Globalization;
 | 
				
			|||||||
using Microsoft.Extensions.Configuration;
 | 
					using Microsoft.Extensions.Configuration;
 | 
				
			||||||
using Microsoft.Extensions.DependencyInjection;
 | 
					using Microsoft.Extensions.DependencyInjection;
 | 
				
			||||||
using Microsoft.Extensions.Logging;
 | 
					using Microsoft.Extensions.Logging;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.Logging.Abstractions;
 | 
				
			||||||
using Serilog;
 | 
					using Serilog;
 | 
				
			||||||
using Serilog.Extensions.Logging;
 | 
					using Serilog.Extensions.Logging;
 | 
				
			||||||
using SQLitePCL;
 | 
					using SQLitePCL;
 | 
				
			||||||
@ -35,7 +37,7 @@ namespace Jellyfin.Server
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        private static readonly CancellationTokenSource _tokenSource = new CancellationTokenSource();
 | 
					        private static readonly CancellationTokenSource _tokenSource = new CancellationTokenSource();
 | 
				
			||||||
        private static readonly ILoggerFactory _loggerFactory = new SerilogLoggerFactory();
 | 
					        private static readonly ILoggerFactory _loggerFactory = new SerilogLoggerFactory();
 | 
				
			||||||
        private static ILogger _logger;
 | 
					        private static ILogger _logger = NullLogger.Instance;
 | 
				
			||||||
        private static bool _restartOnShutdown;
 | 
					        private static bool _restartOnShutdown;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
@ -86,6 +88,12 @@ namespace Jellyfin.Server
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            var stopWatch = new Stopwatch();
 | 
					            var stopWatch = new Stopwatch();
 | 
				
			||||||
            stopWatch.Start();
 | 
					            stopWatch.Start();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Log all uncaught exceptions 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);
 | 
					            ServerApplicationPaths appPaths = CreateApplicationPaths(options);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // $JELLYFIN_LOG_DIR needs to be set for the logger configuration manager
 | 
					            // $JELLYFIN_LOG_DIR needs to be set for the logger configuration manager
 | 
				
			||||||
@ -97,6 +105,8 @@ namespace Jellyfin.Server
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            _logger = _loggerFactory.CreateLogger("Main");
 | 
					            _logger = _loggerFactory.CreateLogger("Main");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Log uncaught exceptions to the logging instead of std error
 | 
				
			||||||
 | 
					            AppDomain.CurrentDomain.UnhandledException -= UnhandledExceptionToConsole;
 | 
				
			||||||
            AppDomain.CurrentDomain.UnhandledException += (sender, e)
 | 
					            AppDomain.CurrentDomain.UnhandledException += (sender, e)
 | 
				
			||||||
                => _logger.LogCritical((Exception)e.ExceptionObject, "Unhandled Exception");
 | 
					                => _logger.LogCritical((Exception)e.ExceptionObject, "Unhandled Exception");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -129,7 +139,7 @@ namespace Jellyfin.Server
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            _logger.LogInformation(
 | 
					            _logger.LogInformation(
 | 
				
			||||||
                "Jellyfin version: {Version}",
 | 
					                "Jellyfin version: {Version}",
 | 
				
			||||||
                Assembly.GetEntryAssembly().GetName().Version.ToString(3));
 | 
					                Assembly.GetEntryAssembly()!.GetName().Version!.ToString(3));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            ApplicationHost.LogEnvironmentInfo(_logger, appPaths);
 | 
					            ApplicationHost.LogEnvironmentInfo(_logger, appPaths);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -354,16 +364,25 @@ namespace Jellyfin.Server
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        private static async Task<IConfiguration> CreateConfiguration(IApplicationPaths appPaths)
 | 
					        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");
 | 
					            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
 | 
					                // For some reason the csproj name is used instead of the assembly name
 | 
				
			||||||
                using (Stream rscstr = typeof(Program).Assembly
 | 
					                using (Stream? resource = typeof(Program).Assembly.GetManifestResourceStream(ResourcePath))
 | 
				
			||||||
                    .GetManifestResourceStream("Jellyfin.Server.Resources.Configuration.logging.json"))
 | 
					 | 
				
			||||||
                using (Stream fstr = File.Open(configPath, FileMode.CreateNew))
 | 
					 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    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);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -426,7 +445,7 @@ namespace Jellyfin.Server
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            _logger.LogInformation("Starting new instance");
 | 
					            _logger.LogInformation("Starting new instance");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            string module = options.RestartPath;
 | 
					            var module = options.RestartPath;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (string.IsNullOrWhiteSpace(module))
 | 
					            if (string.IsNullOrWhiteSpace(module))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@ -434,7 +453,6 @@ namespace Jellyfin.Server
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            string commandLineArgsString;
 | 
					            string commandLineArgsString;
 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (options.RestartArgs != null)
 | 
					            if (options.RestartArgs != null)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                commandLineArgsString = options.RestartArgs ?? string.Empty;
 | 
					                commandLineArgsString = options.RestartArgs ?? string.Empty;
 | 
				
			||||||
 | 
				
			|||||||
@ -13,39 +13,39 @@ namespace Jellyfin.Server
 | 
				
			|||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        /// <value>The path to the data directory.</value>
 | 
					        /// <value>The path to the data directory.</value>
 | 
				
			||||||
        [Option('d', "datadir", Required = false, HelpText = "Path to use for the data folder (database files, etc.).")]
 | 
					        [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>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Gets or sets the path to the web directory.
 | 
					        /// Gets or sets the path to the web directory.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        /// <value>The path to the web directory.</value>
 | 
					        /// <value>The path to the web directory.</value>
 | 
				
			||||||
        [Option('w', "webdir", Required = false, HelpText = "Path to the Jellyfin web UI resources.")]
 | 
					        [Option('w', "webdir", Required = false, HelpText = "Path to the Jellyfin web UI resources.")]
 | 
				
			||||||
        public string WebDir { get; set; }
 | 
					        public string? WebDir { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Gets or sets the path to the cache directory.
 | 
					        /// Gets or sets the path to the cache directory.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        /// <value>The path to the cache directory.</value>
 | 
					        /// <value>The path to the cache directory.</value>
 | 
				
			||||||
        [Option('C', "cachedir", Required = false, HelpText = "Path to use for caching.")]
 | 
					        [Option('C', "cachedir", Required = false, HelpText = "Path to use for caching.")]
 | 
				
			||||||
        public string CacheDir { get; set; }
 | 
					        public string? CacheDir { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Gets or sets the path to the config directory.
 | 
					        /// Gets or sets the path to the config directory.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        /// <value>The path to the config directory.</value>
 | 
					        /// <value>The path to the config directory.</value>
 | 
				
			||||||
        [Option('c', "configdir", Required = false, HelpText = "Path to use for configuration data (user settings and pictures).")]
 | 
					        [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>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Gets or sets the path to the log directory.
 | 
					        /// Gets or sets the path to the log directory.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        /// <value>The path to the log directory.</value>
 | 
					        /// <value>The path to the log directory.</value>
 | 
				
			||||||
        [Option('l', "logdir", Required = false, HelpText = "Path to use for writing log files.")]
 | 
					        [Option('l', "logdir", Required = false, HelpText = "Path to use for writing log files.")]
 | 
				
			||||||
        public string LogDir { get; set; }
 | 
					        public string? LogDir { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <inheritdoc />
 | 
					        /// <inheritdoc />
 | 
				
			||||||
        [Option("ffmpeg", Required = false, HelpText = "Path to external FFmpeg executable to use in place of default found in PATH.")]
 | 
					        [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 />
 | 
					        /// <inheritdoc />
 | 
				
			||||||
        [Option("service", Required = false, HelpText = "Run as headless service.")]
 | 
					        [Option("service", Required = false, HelpText = "Run as headless service.")]
 | 
				
			||||||
@ -57,14 +57,14 @@ namespace Jellyfin.Server
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        /// <inheritdoc />
 | 
					        /// <inheritdoc />
 | 
				
			||||||
        [Option("package-name", Required = false, HelpText = "Used when packaging Jellyfin (example, synology).")]
 | 
					        [Option("package-name", Required = false, HelpText = "Used when packaging Jellyfin (example, synology).")]
 | 
				
			||||||
        public string PackageName { get; set; }
 | 
					        public string? PackageName { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <inheritdoc />
 | 
					        /// <inheritdoc />
 | 
				
			||||||
        [Option("restartpath", Required = false, HelpText = "Path to restart script.")]
 | 
					        [Option("restartpath", Required = false, HelpText = "Path to restart script.")]
 | 
				
			||||||
        public string RestartPath { get; set; }
 | 
					        public string? RestartPath { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <inheritdoc />
 | 
					        /// <inheritdoc />
 | 
				
			||||||
        [Option("restartargs", Required = false, HelpText = "Arguments for restart script.")]
 | 
					        [Option("restartargs", Required = false, HelpText = "Arguments for restart script.")]
 | 
				
			||||||
        public string RestartArgs { get; set; }
 | 
					        public string? RestartArgs { get; set; }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -6,6 +6,8 @@
 | 
				
			|||||||
    <!-- disable warning SA1204: Static members must appear before non-static members -->
 | 
					    <!-- disable warning SA1204: Static members must appear before non-static members -->
 | 
				
			||||||
    <Rule Id="SA1204" Action="Info" />
 | 
					    <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.' -->
 | 
					    <!-- disable warning SA1101: Prefix local calls with 'this.' -->
 | 
				
			||||||
    <Rule Id="SA1101" Action="None" />
 | 
					    <Rule Id="SA1101" Action="None" />
 | 
				
			||||||
    <!-- disable warning SA1108: Block statements should not contain embedded comments -->
 | 
					    <!-- disable warning SA1108: Block statements should not contain embedded comments -->
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user