< Summary - Jellyfin

Information
Class: Jellyfin.Server.Migrations.Routines.ReseedFolderFlag
Assembly: jellyfin
File(s): /srv/git/jellyfin/Jellyfin.Server/Migrations/Routines/ReseedFolderFlag.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 4
Coverable lines: 4
Total lines: 74
Line coverage: 0%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
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
.ctor(...)100%210%

File(s)

/srv/git/jellyfin/Jellyfin.Server/Migrations/Routines/ReseedFolderFlag.cs

#LineLine coverage
 1#pragma warning disable RS0030 // Do not use banned APIs
 2using System.IO;
 3using System.Linq;
 4using System.Threading;
 5using System.Threading.Tasks;
 6using Emby.Server.Implementations.Data;
 7using Jellyfin.Database.Implementations;
 8using Jellyfin.Server.ServerSetupApp;
 9using MediaBrowser.Controller;
 10using Microsoft.Data.Sqlite;
 11using Microsoft.EntityFrameworkCore;
 12using Microsoft.Extensions.Logging;
 13
 14namespace Jellyfin.Server.Migrations.Routines;
 15
 16[JellyfinMigration("2025-07-30T21:50:00", nameof(ReseedFolderFlag))]
 17[JellyfinMigrationBackup(JellyfinDb = true)]
 18internal class ReseedFolderFlag : IAsyncMigrationRoutine
 19{
 20    private const string DbFilename = "library.db.old";
 21
 22    private readonly IStartupLogger _logger;
 23    private readonly IServerApplicationPaths _paths;
 24    private readonly IDbContextFactory<JellyfinDbContext> _provider;
 25
 26    public ReseedFolderFlag(
 27            IStartupLogger<MigrateLibraryDb> startupLogger,
 28            IDbContextFactory<JellyfinDbContext> provider,
 29            IServerApplicationPaths paths)
 30    {
 031        _logger = startupLogger;
 032        _provider = provider;
 033        _paths = paths;
 034    }
 35
 36    internal static bool RerunGuardFlag { get; set; } = false;
 37
 38    public async Task PerformAsync(CancellationToken cancellationToken)
 39    {
 40        if (RerunGuardFlag)
 41        {
 42            _logger.LogInformation("Migration is skipped because it does not apply.");
 43            return;
 44        }
 45
 46        _logger.LogInformation("Migrating the IsFolder flag from library.db.old may take a while, do not stop Jellyfin."
 47
 48        var dataPath = _paths.DataPath;
 49        var libraryDbPath = Path.Combine(dataPath, DbFilename);
 50        if (!File.Exists(libraryDbPath))
 51        {
 52            _logger.LogError("Cannot migrate IsFolder flag from {LibraryDb} as it does not exist. This migration expects
 53            return;
 54        }
 55
 56        var dbContext = await _provider.CreateDbContextAsync(cancellationToken).ConfigureAwait(false);
 57        await using (dbContext.ConfigureAwait(false))
 58        {
 59            using var connection = new SqliteConnection($"Filename={libraryDbPath};Mode=ReadOnly");
 60            var queryResult = connection.Query(
 61                """
 62                    SELECT guid FROM TypedBaseItems
 63                    WHERE IsFolder = true
 64                """)
 65                        .Select(entity => entity.GetGuid(0))
 66                        .ToList();
 67            _logger.LogInformation("Migrating the IsFolder flag for {Count} items.", queryResult.Count);
 68            foreach (var id in queryResult)
 69            {
 70                await dbContext.BaseItems.Where(e => e.Id == id).ExecuteUpdateAsync(e => e.SetProperty(f => f.IsFolder, 
 71            }
 72        }
 73    }
 74}