< Summary - Jellyfin

Information
Class: Jellyfin.Server.Migrations.MigrationRunner
Assembly: jellyfin
File(s): /srv/git/jellyfin/Jellyfin.Server/Migrations/MigrationRunner.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 75
Coverable lines: 75
Total lines: 147
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 10
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%210%
Run(...)100%210%
RunPreStartup(...)0%2040%
HandleStartupWizardCondition(...)0%620%
PerformMigrations(...)0%2040%

File(s)

/srv/git/jellyfin/Jellyfin.Server/Migrations/MigrationRunner.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.IO;
 4using System.Linq;
 5using Emby.Server.Implementations;
 6using Emby.Server.Implementations.Serialization;
 7using MediaBrowser.Common.Configuration;
 8using MediaBrowser.Model.Configuration;
 9using Microsoft.Extensions.DependencyInjection;
 10using Microsoft.Extensions.Logging;
 11
 12namespace Jellyfin.Server.Migrations
 13{
 14    /// <summary>
 15    /// The class that knows which migrations to apply and how to apply them.
 16    /// </summary>
 17    public sealed class MigrationRunner
 18    {
 19        /// <summary>
 20        /// The list of known pre-startup migrations, in order of applicability.
 21        /// </summary>
 022        private static readonly Type[] _preStartupMigrationTypes =
 023        {
 024            typeof(PreStartupRoutines.CreateNetworkConfiguration),
 025            typeof(PreStartupRoutines.MigrateMusicBrainzTimeout),
 026            typeof(PreStartupRoutines.MigrateNetworkConfiguration),
 027            typeof(PreStartupRoutines.MigrateEncodingOptions)
 028        };
 29
 30        /// <summary>
 31        /// The list of known migrations, in order of applicability.
 32        /// </summary>
 033        private static readonly Type[] _migrationTypes =
 034        {
 035            typeof(Routines.DisableTranscodingThrottling),
 036            typeof(Routines.CreateUserLoggingConfigFile),
 037            typeof(Routines.MigrateActivityLogDb),
 038            typeof(Routines.RemoveDuplicateExtras),
 039            typeof(Routines.AddDefaultPluginRepository),
 040            typeof(Routines.MigrateUserDb),
 041            typeof(Routines.ReaddDefaultPluginRepository),
 042            typeof(Routines.MigrateDisplayPreferencesDb),
 043            typeof(Routines.RemoveDownloadImagesInAdvance),
 044            typeof(Routines.MigrateAuthenticationDb),
 045            typeof(Routines.FixPlaylistOwner),
 046            typeof(Routines.MigrateRatingLevels),
 047            typeof(Routines.AddDefaultCastReceivers),
 048            typeof(Routines.UpdateDefaultPluginRepository),
 049            typeof(Routines.FixAudioData),
 050            typeof(Routines.MoveTrickplayFiles)
 051        };
 52
 53        /// <summary>
 54        /// Run all needed migrations.
 55        /// </summary>
 56        /// <param name="host">CoreAppHost that hosts current version.</param>
 57        /// <param name="loggerFactory">Factory for making the logger.</param>
 58        public static void Run(CoreAppHost host, ILoggerFactory loggerFactory)
 59        {
 060            var logger = loggerFactory.CreateLogger<MigrationRunner>();
 061            var migrations = _migrationTypes
 062                .Select(m => ActivatorUtilities.CreateInstance(host.ServiceProvider, m))
 063                .OfType<IMigrationRoutine>()
 064                .ToArray();
 65
 066            var migrationOptions = host.ConfigurationManager.GetConfiguration<MigrationOptions>(MigrationsListStore.Stor
 067            HandleStartupWizardCondition(migrations, migrationOptions, host.ConfigurationManager.Configuration.IsStartup
 068            PerformMigrations(migrations, migrationOptions, options => host.ConfigurationManager.SaveConfiguration(Migra
 069        }
 70
 71        /// <summary>
 72        /// Run all needed pre-startup migrations.
 73        /// </summary>
 74        /// <param name="appPaths">Application paths.</param>
 75        /// <param name="loggerFactory">Factory for making the logger.</param>
 76        public static void RunPreStartup(ServerApplicationPaths appPaths, ILoggerFactory loggerFactory)
 77        {
 078            var logger = loggerFactory.CreateLogger<MigrationRunner>();
 079            var migrations = _preStartupMigrationTypes
 080                .Select(m => Activator.CreateInstance(m, appPaths, loggerFactory))
 081                .OfType<IMigrationRoutine>()
 082                .ToArray();
 83
 084            var xmlSerializer = new MyXmlSerializer();
 085            var migrationConfigPath = Path.Join(appPaths.ConfigurationDirectoryPath, MigrationsListStore.StoreKey.ToLowe
 086            var migrationOptions = File.Exists(migrationConfigPath)
 087                 ? (MigrationOptions)xmlSerializer.DeserializeFromFile(typeof(MigrationOptions), migrationConfigPath)!
 088                 : new MigrationOptions();
 89
 90            // We have to deserialize it manually since the configuration manager may overwrite it
 091            var serverConfig = File.Exists(appPaths.SystemConfigurationFilePath)
 092                ? (ServerConfiguration)xmlSerializer.DeserializeFromFile(typeof(ServerConfiguration), appPaths.SystemCon
 093                : new ServerConfiguration();
 94
 095            HandleStartupWizardCondition(migrations, migrationOptions, serverConfig.IsStartupWizardCompleted, logger);
 096            PerformMigrations(migrations, migrationOptions, options => xmlSerializer.SerializeToFile(options, migrationC
 097        }
 98
 99        private static void HandleStartupWizardCondition(IEnumerable<IMigrationRoutine> migrations, MigrationOptions mig
 100        {
 0101            if (isStartWizardCompleted)
 102            {
 0103                return;
 104            }
 105
 106            // If startup wizard is not finished, this is a fresh install.
 0107            var onlyOldInstalls = migrations.Where(m => !m.PerformOnNewInstall).ToArray();
 0108            logger.LogInformation("Marking following migrations as applied because this is a fresh install: {@OnlyOldIns
 0109            migrationOptions.Applied.AddRange(onlyOldInstalls.Select(m => (m.Id, m.Name)));
 0110        }
 111
 112        private static void PerformMigrations(IMigrationRoutine[] migrations, MigrationOptions migrationOptions, Action<
 113        {
 114            // save already applied migrations, and skip them thereafter
 0115            saveConfiguration(migrationOptions);
 0116            var appliedMigrationIds = migrationOptions.Applied.Select(m => m.Id).ToHashSet();
 117
 0118            for (var i = 0; i < migrations.Length; i++)
 119            {
 0120                var migrationRoutine = migrations[i];
 0121                if (appliedMigrationIds.Contains(migrationRoutine.Id))
 122                {
 0123                    logger.LogDebug("Skipping migration '{Name}' since it is already applied", migrationRoutine.Name);
 0124                    continue;
 125                }
 126
 0127                logger.LogInformation("Applying migration '{Name}'", migrationRoutine.Name);
 128
 129                try
 130                {
 0131                    migrationRoutine.Perform();
 0132                }
 0133                catch (Exception ex)
 134                {
 0135                    logger.LogError(ex, "Could not apply migration '{Name}'", migrationRoutine.Name);
 0136                    throw;
 137                }
 138
 139                // Mark the migration as completed
 0140                logger.LogInformation("Migration '{Name}' applied successfully", migrationRoutine.Name);
 0141                migrationOptions.Applied.Add((migrationRoutine.Id, migrationRoutine.Name));
 0142                saveConfiguration(migrationOptions);
 0143                logger.LogDebug("Migration '{Name}' marked as applied in configuration.", migrationRoutine.Name);
 144            }
 0145        }
 146    }
 147}