Scanner Fix (#2998)

This commit is contained in:
Joe Milazzo 2024-06-12 16:39:08 -05:00 committed by GitHub
parent 6139b3fbdf
commit 11635c6696
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 78 additions and 4 deletions

View File

@ -742,6 +742,9 @@ public class DirectoryServiceTests
[InlineData(new [] {"C:/Manga/"},
new [] {"C:/Manga/Love Hina/Vol. 01.cbz", "C:/Manga/Love Hina/Specials/Sp01.cbz"},
"C:/Manga/Love Hina")]
[InlineData(new [] {"/manga"},
new [] {"/manga/Love Hina/Vol. 01.cbz", "/manga/Love Hina/Specials/Sp01.cbz"},
"/manga/Love Hina")]
public void FindLowestDirectoriesFromFilesTest(string[] rootDirectories, string[] files, string expectedDirectory)
{
var fileSystem = new MockFileSystem();

View File

@ -0,0 +1,59 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using API.Entities;
using API.Services;
using API.Services.Tasks.Scanner.Parser;
using Kavita.Common.EnvironmentInfo;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace API.Data.ManualMigrations;
#nullable enable
/// <summary>
/// Some linux-based users are having non-rooted LowestFolderPaths. This will attempt to fix it or null them.
/// Fixed in v0.8.2
/// </summary>
public static class MigrateSeriesLowestFolderPath
{
public static async Task Migrate(DataContext dataContext, ILogger<Program> logger, IDirectoryService directoryService)
{
if (await dataContext.ManualMigrationHistory.AnyAsync(m => m.Name == "MigrateSeriesLowestFolderPath"))
{
return;
}
logger.LogCritical("Running MigrateSeriesLowestFolderPath migration - Please be patient, this may take some time. This is not an error");
var seriesWithFolderPath =
await dataContext.Series.Where(s => !string.IsNullOrEmpty(s.LowestFolderPath))
.Include(s => s.Library)
.ThenInclude(l => l.Folders)
.ToListAsync();
foreach (var series in seriesWithFolderPath)
{
var isValidPath = series.Library.Folders
.Any(folder => Parser.NormalizePath(series.LowestFolderPath!).StartsWith(Parser.NormalizePath(folder.Path), StringComparison.OrdinalIgnoreCase));
if (isValidPath) continue;
series.LowestFolderPath = null;
dataContext.Entry(series).State = EntityState.Modified;
}
await dataContext.SaveChangesAsync();
dataContext.ManualMigrationHistory.Add(new ManualMigrationHistory()
{
Name = "MigrateSeriesLowestFolderPath",
ProductVersion = BuildInfo.Version.ToString(),
RanAt = DateTime.UtcNow
});
await dataContext.SaveChangesAsync();
logger.LogCritical("Running MigrateSeriesLowestFolderPath migration - Completed. This is not an error");
}
}

View File

@ -3,7 +3,9 @@ using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using API.DTOs.Filtering.v2;
using API.Entities;
using API.Helpers;
using Kavita.Common.EnvironmentInfo;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
@ -29,7 +31,7 @@ public static class MigrateSmartFilterEncoding
logger.LogCritical("Running MigrateSmartFilterEncoding migration - Please be patient, this may take some time. This is not an error");
var smartFilters = dataContext.AppUserSmartFilter.ToList();
var smartFilters = await dataContext.AppUserSmartFilter.ToListAsync();
foreach (var filter in smartFilters)
{
if (!ShouldMigrateFilter(filter.Filter)) continue;
@ -43,6 +45,14 @@ public static class MigrateSmartFilterEncoding
await unitOfWork.CommitAsync();
}
dataContext.ManualMigrationHistory.Add(new ManualMigrationHistory()
{
Name = "MigrateSmartFilterEncoding",
ProductVersion = BuildInfo.Version.ToString(),
RanAt = DateTime.UtcNow
});
await dataContext.SaveChangesAsync();
logger.LogCritical("Running MigrateSmartFilterEncoding migration - Completed. This is not an error");
}

View File

@ -745,12 +745,12 @@ public class DirectoryService : IDirectoryService
/// <summary>
/// Recursively scans a folder and returns the max last write time on any folders and files
/// </summary>
/// <remarks>If the folder is empty, this will return MaxValue for a DateTime</remarks>
/// <remarks>If the folder is empty or non-existant, this will return MaxValue for a DateTime</remarks>
/// <param name="folderPath"></param>
/// <returns>Max Last Write Time</returns>
public DateTime GetLastWriteTime(string folderPath)
{
if (!FileSystem.Directory.Exists(folderPath)) throw new IOException($"{folderPath} does not exist");
if (!FileSystem.Directory.Exists(folderPath)) return DateTime.MaxValue;
var fileEntries = FileSystem.Directory.GetFileSystemEntries(folderPath, "*.*", SearchOption.AllDirectories);
if (fileEntries.Length == 0) return DateTime.MaxValue;
return fileEntries.Max(path => FileSystem.File.GetLastWriteTime(path));

View File

@ -143,7 +143,8 @@ public class ParseScannedFiles
_logger.LogDebug("[ProcessFiles] Dirty check passed, series list: {@SeriesModified}", series2);
foreach (var s in series2)
{
_logger.LogDebug("[ProcessFiles] Last Scanned: {LastScanned} vs Directory Check: {DirectoryLastScanned}", s.LastScanned, _directoryService
_logger.LogDebug("[ProcessFiles] Last Scanned: {LastScanned} vs Directory Check: {DirectoryLastScanned}",
s.LastScanned, _directoryService
.GetLastWriteTime(s.LowestFolderPath!)
.Truncate(TimeSpan.TicksPerSecond));
}

View File

@ -269,6 +269,7 @@ public class Startup
// v0.8.2
await ManualMigrateThemeDescription.Migrate(dataContext, logger);
await MigrateInitialInstallData.Migrate(dataContext, logger, directoryService);
await MigrateSeriesLowestFolderPath.Migrate(dataContext, logger, directoryService);
// Update the version in the DB after all migrations are run
var installVersion = await unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.InstallVersion);