diff options
| -rw-r--r-- | Emby.Naming/Emby.Naming.csproj | 2 | ||||
| -rw-r--r-- | Emby.Photos/Emby.Photos.csproj | 2 | ||||
| -rw-r--r-- | Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs | 2 | ||||
| -rw-r--r-- | Emby.Server.Implementations/Emby.Server.Implementations.csproj | 9 | ||||
| -rw-r--r-- | Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs | 21 | ||||
| -rw-r--r-- | Emby.Server.Implementations/Updates/InstallationManager.cs | 176 | ||||
| -rw-r--r-- | Jellyfin.Server/CoreAppHost.cs | 17 | ||||
| -rw-r--r-- | Jellyfin.Server/Jellyfin.Server.csproj | 10 | ||||
| -rw-r--r-- | Jellyfin.Server/Program.cs | 27 | ||||
| -rw-r--r-- | Jellyfin.Server/StartupOptions.cs | 26 | ||||
| -rw-r--r-- | MediaBrowser.Api/PackageService.cs | 10 | ||||
| -rw-r--r-- | MediaBrowser.Common/Updates/IInstallationManager.cs | 16 | ||||
| -rw-r--r-- | MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj | 2 | ||||
| -rw-r--r-- | MediaBrowser.Model/Updates/PackageVersionInfo.cs | 22 | ||||
| -rw-r--r-- | MediaBrowser.Providers/Omdb/OmdbProvider.cs | 3 |
15 files changed, 180 insertions, 165 deletions
diff --git a/Emby.Naming/Emby.Naming.csproj b/Emby.Naming/Emby.Naming.csproj index 9e2a4950f..0b1ce2fce 100644 --- a/Emby.Naming/Emby.Naming.csproj +++ b/Emby.Naming/Emby.Naming.csproj @@ -23,7 +23,7 @@ <!-- Code analysers--> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> - <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.3" /> + <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.4" /> <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" /> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" /> </ItemGroup> diff --git a/Emby.Photos/Emby.Photos.csproj b/Emby.Photos/Emby.Photos.csproj index c9830abc5..8a79bf7e1 100644 --- a/Emby.Photos/Emby.Photos.csproj +++ b/Emby.Photos/Emby.Photos.csproj @@ -10,7 +10,7 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="TagLibSharp" Version="2.2.0-beta" /> + <PackageReference Include="TagLibSharp" Version="2.2.0" /> </ItemGroup> <PropertyGroup> diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs index 3e44c9c0a..fb4ffd74b 100644 --- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs +++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs @@ -346,7 +346,7 @@ namespace Emby.Server.Implementations.Activity }); } - private void OnPluginUpdated(object sender, GenericEventArgs<Tuple<IPlugin, PackageVersionInfo>> e) + private void OnPluginUpdated(object sender, GenericEventArgs<(IPlugin, PackageVersionInfo)> e) { CreateLogEntry(new ActivityLogEntry { diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index f07f8e3bf..c78d96d4a 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -32,7 +32,7 @@ <PackageReference Include="Microsoft.Extensions.Logging" Version="2.2.0" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.2.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="2.2.0" /> - <PackageReference Include="ServiceStack.Text.Core" Version="5.5.0" /> + <PackageReference Include="ServiceStack.Text.Core" Version="5.6.0" /> <PackageReference Include="sharpcompress" Version="0.23.0" /> <PackageReference Include="SQLitePCL.pretty.netstandard" Version="1.0.0" /> </ItemGroup> @@ -47,13 +47,14 @@ <GenerateDocumentationFile>true</GenerateDocumentationFile> </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)' == 'Release' "> - <TreatWarningsAsErrors>true</TreatWarningsAsErrors> + <PropertyGroup> + <!-- We need at least C# 7.3 to compare tuples--> + <LangVersion>latest</LangVersion> </PropertyGroup> <!-- Code analysers--> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> - <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.3" /> + <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.4" /> <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" /> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" /> </ItemGroup> diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs index c6431c311..bde7d5c81 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs @@ -1,4 +1,3 @@ -using MediaBrowser.Common; using MediaBrowser.Common.Updates; using MediaBrowser.Model.Net; using System; @@ -25,13 +24,10 @@ namespace Emby.Server.Implementations.ScheduledTasks private readonly IInstallationManager _installationManager; - private readonly IApplicationHost _appHost; - - public PluginUpdateTask(ILogger logger, IInstallationManager installationManager, IApplicationHost appHost) + public PluginUpdateTask(ILogger logger, IInstallationManager installationManager) { _logger = logger; _installationManager = installationManager; - _appHost = appHost; } /// <summary> @@ -40,14 +36,11 @@ namespace Emby.Server.Implementations.ScheduledTasks /// <returns>IEnumerable{BaseTaskTrigger}.</returns> public IEnumerable<TaskTriggerInfo> GetDefaultTriggers() { - return new[] { - - // At startup - new TaskTriggerInfo {Type = TaskTriggerInfo.TriggerStartup}, - - // Every so often - new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks} - }; + // At startup + yield return new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerStartup }; + + // Every so often + yield return new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks }; } /// <summary> @@ -72,7 +65,7 @@ namespace Emby.Server.Implementations.ScheduledTasks try { - await _installationManager.InstallPackage(package, true, new SimpleProgress<double>(), cancellationToken).ConfigureAwait(false); + await _installationManager.InstallPackage(package, new SimpleProgress<double>(), cancellationToken).ConfigureAwait(false); } catch (OperationCanceledException) { diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index 6833c20c3..9bc85633d 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -3,6 +3,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Net.Http; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common; @@ -33,7 +34,7 @@ namespace Emby.Server.Implementations.Updates /// <summary> /// The current installations /// </summary> - public List<Tuple<InstallationInfo, CancellationTokenSource>> CurrentInstallations { get; set; } + private List<(InstallationInfo info, CancellationTokenSource token)> _currentInstallations { get; set; } /// <summary> /// The completed installations @@ -48,48 +49,14 @@ namespace Emby.Server.Implementations.Updates public event EventHandler<GenericEventArgs<IPlugin>> PluginUninstalled; /// <summary> - /// Called when [plugin uninstalled]. - /// </summary> - /// <param name="plugin">The plugin.</param> - private void OnPluginUninstalled(IPlugin plugin) - { - PluginUninstalled?.Invoke(this, new GenericEventArgs<IPlugin> { Argument = plugin }); - } - - /// <summary> /// Occurs when [plugin updated]. /// </summary> - public event EventHandler<GenericEventArgs<Tuple<IPlugin, PackageVersionInfo>>> PluginUpdated; - /// <summary> - /// Called when [plugin updated]. - /// </summary> - /// <param name="plugin">The plugin.</param> - /// <param name="newVersion">The new version.</param> - private void OnPluginUpdated(IPlugin plugin, PackageVersionInfo newVersion) - { - _logger.LogInformation("Plugin updated: {0} {1} {2}", newVersion.name, newVersion.versionStr ?? string.Empty, newVersion.classification); - - PluginUpdated?.Invoke(this, new GenericEventArgs<Tuple<IPlugin, PackageVersionInfo>> { Argument = new Tuple<IPlugin, PackageVersionInfo>(plugin, newVersion) }); - - _applicationHost.NotifyPendingRestart(); - } + public event EventHandler<GenericEventArgs<(IPlugin, PackageVersionInfo)>> PluginUpdated; /// <summary> /// Occurs when [plugin updated]. /// </summary> public event EventHandler<GenericEventArgs<PackageVersionInfo>> PluginInstalled; - /// <summary> - /// Called when [plugin installed]. - /// </summary> - /// <param name="package">The package.</param> - private void OnPluginInstalled(PackageVersionInfo package) - { - _logger.LogInformation("New plugin installed: {0} {1} {2}", package.name, package.versionStr ?? string.Empty, package.classification); - - PluginInstalled?.Invoke(this, new GenericEventArgs<PackageVersionInfo> { Argument = package }); - - _applicationHost.NotifyPendingRestart(); - } /// <summary> /// The _logger @@ -111,7 +78,7 @@ namespace Emby.Server.Implementations.Updates private readonly IZipClient _zipClient; public InstallationManager( - ILoggerFactory loggerFactory, + ILogger<InstallationManager> logger, IApplicationHost appHost, IApplicationPaths appPaths, IHttpClient httpClient, @@ -120,15 +87,15 @@ namespace Emby.Server.Implementations.Updates IFileSystem fileSystem, IZipClient zipClient) { - if (loggerFactory == null) + if (logger == null) { - throw new ArgumentNullException(nameof(loggerFactory)); + throw new ArgumentNullException(nameof(logger)); } - CurrentInstallations = new List<Tuple<InstallationInfo, CancellationTokenSource>>(); + _currentInstallations = new List<(InstallationInfo, CancellationTokenSource)>(); _completedInstallationsInternal = new ConcurrentBag<InstallationInfo>(); - _logger = loggerFactory.CreateLogger(nameof(InstallationManager)); + _logger = logger; _applicationHost = appHost; _appPaths = appPaths; _httpClient = httpClient; @@ -138,21 +105,12 @@ namespace Emby.Server.Implementations.Updates _zipClient = zipClient; } - private static Version GetPackageVersion(PackageVersionInfo version) - { - return new Version(ValueOrDefault(version.versionStr, "0.0.0.1")); - } - - private static string ValueOrDefault(string str, string def) - { - return string.IsNullOrEmpty(str) ? def : str; - } - /// <summary> /// Gets all available packages. /// </summary> /// <returns>Task{List{PackageInfo}}.</returns> - public async Task<List<PackageInfo>> GetAvailablePackages(CancellationToken cancellationToken, + public async Task<List<PackageInfo>> GetAvailablePackages( + CancellationToken cancellationToken, bool withRegistration = true, string packageType = null, Version applicationVersion = null) @@ -172,22 +130,14 @@ namespace Emby.Server.Implementations.Updates { Url = "https://repo.jellyfin.org/releases/plugin/manifest.json", CancellationToken = cancellationToken, - Progress = new SimpleProgress<double>(), CacheLength = GetCacheLength() - }, "GET").ConfigureAwait(false)) + }, HttpMethod.Get).ConfigureAwait(false)) + using (var stream = response.Content) { - using (var stream = response.Content) - { - return FilterPackages(await _jsonSerializer.DeserializeFromStreamAsync<PackageInfo[]>(stream).ConfigureAwait(false)); - } + return FilterPackages(await _jsonSerializer.DeserializeFromStreamAsync<PackageInfo[]>(stream).ConfigureAwait(false)); } } - private PackageVersionClass GetSystemUpdateLevel() - { - return _applicationHost.SystemUpdateLevel; - } - private static TimeSpan GetCacheLength() { return TimeSpan.FromMinutes(3); @@ -211,7 +161,7 @@ namespace Emby.Server.Implementations.Updates } package.versions = versions - .OrderByDescending(GetPackageVersion) + .OrderByDescending(x => x.Version) .ToArray(); if (package.versions.Length == 0) @@ -294,7 +244,7 @@ namespace Emby.Server.Implementations.Updates return null; } - return package.versions.FirstOrDefault(v => GetPackageVersion(v).Equals(version) && v.classification == classification); + return package.versions.FirstOrDefault(v => v.Version == version && v.classification == classification); } /// <summary> @@ -331,7 +281,7 @@ namespace Emby.Server.Implementations.Updates } return package.versions - .OrderByDescending(GetPackageVersion) + .OrderByDescending(x => x.Version) .FirstOrDefault(v => v.classification <= classification && IsPackageVersionUpToDate(v, currentServerVersion)); } @@ -346,14 +296,14 @@ namespace Emby.Server.Implementations.Updates { var catalog = await GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false); - var systemUpdateLevel = GetSystemUpdateLevel(); + var systemUpdateLevel = _applicationHost.SystemUpdateLevel; // Figure out what needs to be installed return _applicationHost.Plugins.Select(p => { var latestPluginInfo = GetLatestCompatibleVersion(catalog, p.Name, p.Id.ToString(), applicationVersion, systemUpdateLevel); - return latestPluginInfo != null && GetPackageVersion(latestPluginInfo) > p.Version ? latestPluginInfo : null; + return latestPluginInfo != null && latestPluginInfo.Version > p.Version ? latestPluginInfo : null; }).Where(i => i != null) .Where(p => !string.IsNullOrEmpty(p.sourceUrl) && !CompletedInstallations.Any(i => string.Equals(i.AssemblyGuid, p.guid, StringComparison.OrdinalIgnoreCase))); @@ -368,7 +318,7 @@ namespace Emby.Server.Implementations.Updates /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> /// <exception cref="ArgumentNullException">package</exception> - public async Task InstallPackage(PackageVersionInfo package, bool isPlugin, IProgress<double> progress, CancellationToken cancellationToken) + public async Task InstallPackage(PackageVersionInfo package, IProgress<double> progress, CancellationToken cancellationToken) { if (package == null) { @@ -391,12 +341,12 @@ namespace Emby.Server.Implementations.Updates var innerCancellationTokenSource = new CancellationTokenSource(); - var tuple = new Tuple<InstallationInfo, CancellationTokenSource>(installationInfo, innerCancellationTokenSource); + var tuple = (installationInfo, innerCancellationTokenSource); // Add it to the in-progress list - lock (CurrentInstallations) + lock (_currentInstallations) { - CurrentInstallations.Add(tuple); + _currentInstallations.Add(tuple); } var innerProgress = new ActionableProgress<double>(); @@ -421,11 +371,11 @@ namespace Emby.Server.Implementations.Updates try { - await InstallPackageInternal(package, isPlugin, innerProgress, linkedToken).ConfigureAwait(false); + await InstallPackageInternal(package, innerProgress, linkedToken).ConfigureAwait(false); - lock (CurrentInstallations) + lock (_currentInstallations) { - CurrentInstallations.Remove(tuple); + _currentInstallations.Remove(tuple); } _completedInstallationsInternal.Add(installationInfo); @@ -434,9 +384,9 @@ namespace Emby.Server.Implementations.Updates } catch (OperationCanceledException) { - lock (CurrentInstallations) + lock (_currentInstallations) { - CurrentInstallations.Remove(tuple); + _currentInstallations.Remove(tuple); } _logger.LogInformation("Package installation cancelled: {0} {1}", package.name, package.versionStr); @@ -449,9 +399,9 @@ namespace Emby.Server.Implementations.Updates { _logger.LogError(ex, "Package installation failed"); - lock (CurrentInstallations) + lock (_currentInstallations) { - CurrentInstallations.Remove(tuple); + _currentInstallations.Remove(tuple); } PackageInstallationFailed?.Invoke(this, new InstallationFailedEventArgs @@ -477,16 +427,11 @@ namespace Emby.Server.Implementations.Updates /// <param name="progress">The progress.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - private async Task InstallPackageInternal(PackageVersionInfo package, bool isPlugin, IProgress<double> progress, CancellationToken cancellationToken) + private async Task InstallPackageInternal(PackageVersionInfo package, IProgress<double> progress, CancellationToken cancellationToken) { - IPlugin plugin = null; - - if (isPlugin) - { - // Set last update time if we were installed before - plugin = _applicationHost.Plugins.FirstOrDefault(p => string.Equals(p.Id.ToString(), package.guid, StringComparison.OrdinalIgnoreCase)) + // Set last update time if we were installed before + IPlugin plugin = _applicationHost.Plugins.FirstOrDefault(p => string.Equals(p.Id.ToString(), package.guid, StringComparison.OrdinalIgnoreCase)) ?? _applicationHost.Plugins.FirstOrDefault(p => p.Name.Equals(package.name, StringComparison.OrdinalIgnoreCase)); - } string targetPath = plugin == null ? null : plugin.AssemblyFilePath; @@ -494,17 +439,20 @@ namespace Emby.Server.Implementations.Updates await PerformPackageInstallation(progress, targetPath, package, cancellationToken).ConfigureAwait(false); // Do plugin-specific processing - if (isPlugin) + if (plugin == null) { - if (plugin == null) - { - OnPluginInstalled(package); - } - else - { - OnPluginUpdated(plugin, package); - } + _logger.LogInformation("New plugin installed: {0} {1} {2}", package.name, package.versionStr ?? string.Empty, package.classification); + + PluginInstalled?.Invoke(this, new GenericEventArgs<PackageVersionInfo>(package)); } + else + { + _logger.LogInformation("Plugin updated: {0} {1} {2}", package.name, package.versionStr ?? string.Empty, package.classification); + + PluginUpdated?.Invoke(this, new GenericEventArgs<(IPlugin, PackageVersionInfo)>((plugin, package))); + } + + _applicationHost.NotifyPendingRestart(); } private async Task PerformPackageInstallation(IProgress<double> progress, string target, PackageVersionInfo package, CancellationToken cancellationToken) @@ -622,11 +570,34 @@ namespace Emby.Server.Implementations.Updates _config.SaveConfiguration(); } - OnPluginUninstalled(plugin); + PluginUninstalled?.Invoke(this, new GenericEventArgs<IPlugin> { Argument = plugin }); _applicationHost.NotifyPendingRestart(); } + /// <inheritdoc/> + public bool CancelInstallation(Guid id) + { + lock (_currentInstallations) + { + var install = _currentInstallations.Find(x => x.Item1.Id == id); + if (install == default((InstallationInfo, CancellationTokenSource))) + { + return false; + } + + install.Item2.Cancel(); + _currentInstallations.Remove(install); + return true; + } + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + /// <summary> /// Releases unmanaged and - optionally - managed resources. /// </summary> @@ -635,21 +606,16 @@ namespace Emby.Server.Implementations.Updates { if (dispose) { - lock (CurrentInstallations) + lock (_currentInstallations) { - foreach (var tuple in CurrentInstallations) + foreach (var tuple in _currentInstallations) { tuple.Item2.Dispose(); } - CurrentInstallations.Clear(); + _currentInstallations.Clear(); } } } - - public void Dispose() - { - Dispose(true); - } } } diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index b9b0cc382..8b4b61e29 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -9,8 +9,21 @@ using Microsoft.Extensions.Logging; namespace Jellyfin.Server { + /// <summary> + /// Implementation of the abstract <see cref="ApplicationHost" /> class. + /// </summary> public class CoreAppHost : ApplicationHost { + /// <summary> + /// Initializes a new instance of the <see cref="CoreAppHost" /> class. + /// </summary> + /// <param name="applicationPaths">The <see cref="ServerApplicationPaths" /> to be used by the <see cref="CoreAppHost" />.</param> + /// <param name="loggerFactory">The <see cref="ILoggerFactory" /> to be used by the <see cref="CoreAppHost" />.</param> + /// <param name="options">The <see cref="StartupOptions" /> to be used by the <see cref="CoreAppHost" />.</param> + /// <param name="fileSystem">The <see cref="IFileSystem" /> to be used by the <see cref="CoreAppHost" />.</param> + /// <param name="imageEncoder">The <see cref="IImageEncoder" /> to be used by the <see cref="CoreAppHost" />.</param> + /// <param name="networkManager">The <see cref="INetworkManager" /> to be used by the <see cref="CoreAppHost" />.</param> + /// <param name="configuration">The <see cref="IConfiguration" /> to be used by the <see cref="CoreAppHost" />.</param> public CoreAppHost( ServerApplicationPaths applicationPaths, ILoggerFactory loggerFactory, @@ -30,15 +43,19 @@ namespace Jellyfin.Server { } + /// <inheritdoc /> public override bool CanSelfRestart => StartupOptions.RestartPath != null; + /// <inheritdoc /> protected override void RestartInternal() => Program.Restart(); + /// <inheritdoc /> protected override IEnumerable<Assembly> GetAssembliesWithPartsInternal() { yield return typeof(CoreAppHost).Assembly; } + /// <inheritdoc /> protected override void ShutdownInternal() => Program.Shutdown(); } } diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 641b3f182..e87283477 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -9,10 +9,8 @@ </PropertyGroup> <PropertyGroup> - <!-- We need C# 7.1 for async main--> + <!-- We need at least C# 7.1 for async main--> <LangVersion>latest</LangVersion> - <!-- Disable documentation warnings (for now) --> - <NoWarn>SA1600;SA1601;SA1629;CS1591</NoWarn> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> </PropertyGroup> @@ -26,7 +24,7 @@ <!-- Code analysers--> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> - <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.3" /> + <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.4" /> <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" /> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" /> </ItemGroup> @@ -36,7 +34,7 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="CommandLineParser" Version="2.5.0" /> + <PackageReference Include="CommandLineParser" Version="2.6.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.2.4" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.2.0" /> <PackageReference Include="Serilog.AspNetCore" Version="2.1.1" /> @@ -45,7 +43,7 @@ <PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" /> <PackageReference Include="Serilog.Sinks.File" Version="4.0.0" /> <PackageReference Include="SkiaSharp" Version="1.68.0" /> - <PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="1.1.14" /> + <PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.0.0" /> <PackageReference Include="SQLitePCLRaw.provider.sqlite3.netstandard11" Version="1.1.14" /> </ItemGroup> diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 952990493..5e4e36a34 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -28,6 +28,9 @@ using ILogger = Microsoft.Extensions.Logging.ILogger; namespace Jellyfin.Server { + /// <summary> + /// Class containing the entry point of the application. + /// </summary> public static class Program { private static readonly CancellationTokenSource _tokenSource = new CancellationTokenSource(); @@ -35,6 +38,11 @@ namespace Jellyfin.Server private static ILogger _logger; private static bool _restartOnShutdown; + /// <summary> + /// The entry point of the application. + /// </summary> + /// <param name="args">The command line arguments passed.</param> + /// <returns><see cref="Task" />.</returns> public static Task Main(string[] args) { // For backwards compatibility. @@ -53,7 +61,10 @@ namespace Jellyfin.Server .MapResult(StartApp, _ => Task.CompletedTask); } - public static void Shutdown() + /// <summary> + /// Shuts down the application. + /// </summary> + internal static void Shutdown() { if (!_tokenSource.IsCancellationRequested) { @@ -61,7 +72,10 @@ namespace Jellyfin.Server } } - public static void Restart() + /// <summary> + /// Restarts the application. + /// </summary> + internal static void Restart() { _restartOnShutdown = true; @@ -171,11 +185,12 @@ namespace Jellyfin.Server /// <summary> /// Create the data, config and log paths from the variety of inputs(command line args, /// environment variables) or decide on what default to use. For Windows it's %AppPath% - /// for everything else the XDG approach is followed: - /// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html + /// for everything else the + /// <a href="https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html">XDG approach</a> + /// is followed. /// </summary> - /// <param name="options">StartupOptions</param> - /// <returns>ServerApplicationPaths</returns> + /// <param name="options">The <see cref="StartupOptions" /> for this instance.</param> + /// <returns><see cref="ServerApplicationPaths" />.</returns> private static ServerApplicationPaths CreateApplicationPaths(StartupOptions options) { // dataDir diff --git a/Jellyfin.Server/StartupOptions.cs b/Jellyfin.Server/StartupOptions.cs index 8296d414e..bb0adaf63 100644 --- a/Jellyfin.Server/StartupOptions.cs +++ b/Jellyfin.Server/StartupOptions.cs @@ -8,36 +8,62 @@ namespace Jellyfin.Server /// </summary> public class StartupOptions : IStartupOptions { + /// <summary> + /// Gets or sets the path to the data directory. + /// </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; } + /// <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; } + /// <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; } + /// <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; } + /// <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; } + /// <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; } + /// <inheritdoc /> [Option("service", Required = false, HelpText = "Run as headless service.")] public bool IsService { get; set; } + /// <inheritdoc /> [Option("noautorunwebapp", Required = false, HelpText = "Run headless if startup wizard is complete.")] public bool NoAutoRunWebApp { get; set; } + /// <inheritdoc /> [Option("package-name", Required = false, HelpText = "Used when packaging Jellyfin (example, synology).")] public string PackageName { get; set; } + /// <inheritdoc /> [Option("restartpath", Required = false, HelpText = "Path to restart script.")] public string RestartPath { get; set; } + /// <inheritdoc /> [Option("restartargs", Required = false, HelpText = "Arguments for restart script.")] public string RestartArgs { get; set; } } diff --git a/MediaBrowser.Api/PackageService.cs b/MediaBrowser.Api/PackageService.cs index fbb876dea..cf1e08d53 100644 --- a/MediaBrowser.Api/PackageService.cs +++ b/MediaBrowser.Api/PackageService.cs @@ -197,7 +197,7 @@ namespace MediaBrowser.Api throw new ResourceNotFoundException(string.Format("Package not found: {0}", request.Name)); } - await _installationManager.InstallPackage(package, true, new SimpleProgress<double>(), CancellationToken.None); + await _installationManager.InstallPackage(package, new SimpleProgress<double>(), CancellationToken.None); } /// <summary> @@ -206,13 +206,7 @@ namespace MediaBrowser.Api /// <param name="request">The request.</param> public void Delete(CancelPackageInstallation request) { - var info = _installationManager.CurrentInstallations.FirstOrDefault(i => i.Item1.Id.Equals(request.Id)); - - if (info != null) - { - info.Item2.Cancel(); - } + _installationManager.CancelInstallation(new Guid(request.Id)); } } - } diff --git a/MediaBrowser.Common/Updates/IInstallationManager.cs b/MediaBrowser.Common/Updates/IInstallationManager.cs index a263be35f..3472a5692 100644 --- a/MediaBrowser.Common/Updates/IInstallationManager.cs +++ b/MediaBrowser.Common/Updates/IInstallationManager.cs @@ -16,11 +16,6 @@ namespace MediaBrowser.Common.Updates event EventHandler<InstallationEventArgs> PackageInstallationCancelled; /// <summary> - /// The current installations - /// </summary> - List<Tuple<InstallationInfo, CancellationTokenSource>> CurrentInstallations { get; set; } - - /// <summary> /// The completed installations /// </summary> IEnumerable<InstallationInfo> CompletedInstallations { get; } @@ -33,7 +28,7 @@ namespace MediaBrowser.Common.Updates /// <summary> /// Occurs when [plugin updated]. /// </summary> - event EventHandler<GenericEventArgs<Tuple<IPlugin, PackageVersionInfo>>> PluginUpdated; + event EventHandler<GenericEventArgs<(IPlugin, PackageVersionInfo)>> PluginUpdated; /// <summary> /// Occurs when [plugin updated]. @@ -107,7 +102,7 @@ namespace MediaBrowser.Common.Updates /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> /// <exception cref="ArgumentNullException">package</exception> - Task InstallPackage(PackageVersionInfo package, bool isPlugin, IProgress<double> progress, CancellationToken cancellationToken); + Task InstallPackage(PackageVersionInfo package, IProgress<double> progress, CancellationToken cancellationToken); /// <summary> /// Uninstalls a plugin @@ -115,5 +110,12 @@ namespace MediaBrowser.Common.Updates /// <param name="plugin">The plugin.</param> /// <exception cref="ArgumentException"></exception> void UninstallPlugin(IPlugin plugin); + + /// <summary> + /// Cancels the installation + /// </summary> + /// <param name="id">The id of the package that is being installed</param> + /// <returns>Returns true if the install was cancelled</returns> + bool CancelInstallation(Guid id); } } diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index c0f92ac4a..681a2e372 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -18,7 +18,7 @@ <ItemGroup> <PackageReference Include="System.Text.Encoding.CodePages" Version="4.5.1" /> - <PackageReference Include="UTF.Unknown" Version="1.0.0" /> + <PackageReference Include="UTF.Unknown" Version="2.0.0" /> </ItemGroup> </Project> diff --git a/MediaBrowser.Model/Updates/PackageVersionInfo.cs b/MediaBrowser.Model/Updates/PackageVersionInfo.cs index be531770d..7ef07c0df 100644 --- a/MediaBrowser.Model/Updates/PackageVersionInfo.cs +++ b/MediaBrowser.Model/Updates/PackageVersionInfo.cs @@ -30,23 +30,25 @@ namespace MediaBrowser.Model.Updates /// The _version /// </summary> private Version _version; + /// <summary> /// Gets or sets the version. /// Had to make this an interpreted property since Protobuf can't handle Version /// </summary> /// <value>The version.</value> [IgnoreDataMember] - public Version version => _version ?? (_version = new Version(ValueOrDefault(versionStr, "0.0.0.1"))); - - /// <summary> - /// Values the or default. - /// </summary> - /// <param name="str">The STR.</param> - /// <param name="def">The def.</param> - /// <returns>System.String.</returns> - private static string ValueOrDefault(string str, string def) + public Version Version { - return string.IsNullOrEmpty(str) ? def : str; + get + { + if (_version == null) + { + var ver = versionStr; + _version = new Version(string.IsNullOrEmpty(ver) ? "0.0.0.1" : ver); + } + + return _version; + } } /// <summary> diff --git a/MediaBrowser.Providers/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Omdb/OmdbProvider.cs index 19dce34d6..f8b876580 100644 --- a/MediaBrowser.Providers/Omdb/OmdbProvider.cs +++ b/MediaBrowser.Providers/Omdb/OmdbProvider.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; +using System.Net.Http; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -347,7 +348,7 @@ namespace MediaBrowser.Providers.Omdb CancellationToken = cancellationToken, BufferContent = true, EnableDefaultUserAgent = true - }, "GET"); + }, HttpMethod.Get); } internal string GetDataFilePath(string imdbId) |
