mirror of
https://github.com/Sonarr/Sonarr.git
synced 2025-04-23 22:07:07 -04:00
Fixed: Delete orphaned extra and subtitle files during housekeeping
Closes #7785
This commit is contained in:
parent
b103005aa2
commit
23ee08a573
4 changed files with 355 additions and 0 deletions
|
@ -0,0 +1,121 @@
|
|||
using System.Collections.Generic;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Extras.Others;
|
||||
using NzbDrone.Core.Housekeeping.Housekeepers;
|
||||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
|
||||
{
|
||||
[TestFixture]
|
||||
public class CleanupOrphanedExtraFilesFixture : DbTest<CleanupOrphanedExtraFiles, OtherExtraFile>
|
||||
{
|
||||
[Test]
|
||||
public void should_delete_extra_files_that_dont_have_a_coresponding_series()
|
||||
{
|
||||
var episodeFile = Builder<EpisodeFile>.CreateNew()
|
||||
.With(h => h.Quality = new QualityModel())
|
||||
.With(h => h.Languages = new List<Language> { Language.English })
|
||||
.BuildNew();
|
||||
|
||||
Db.Insert(episodeFile);
|
||||
|
||||
var extraFile = Builder<OtherExtraFile>.CreateNew()
|
||||
.With(m => m.EpisodeFileId = episodeFile.Id)
|
||||
.BuildNew();
|
||||
|
||||
Db.Insert(extraFile);
|
||||
Subject.Clean();
|
||||
AllStoredModels.Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_delete_extra_files_that_have_a_coresponding_series()
|
||||
{
|
||||
var series = Builder<Series>.CreateNew()
|
||||
.BuildNew();
|
||||
|
||||
var episodeFile = Builder<EpisodeFile>.CreateNew()
|
||||
.With(h => h.Quality = new QualityModel())
|
||||
.With(h => h.Languages = new List<Language> { Language.English })
|
||||
.BuildNew();
|
||||
|
||||
Db.Insert(series);
|
||||
Db.Insert(episodeFile);
|
||||
|
||||
var extraFile = Builder<OtherExtraFile>.CreateNew()
|
||||
.With(m => m.SeriesId = series.Id)
|
||||
.With(m => m.EpisodeFileId = episodeFile.Id)
|
||||
.BuildNew();
|
||||
|
||||
Db.Insert(extraFile);
|
||||
Subject.Clean();
|
||||
AllStoredModels.Should().HaveCount(1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_delete_extra_files_that_dont_have_a_coresponding_episode_file()
|
||||
{
|
||||
var series = Builder<Series>.CreateNew()
|
||||
.BuildNew();
|
||||
|
||||
Db.Insert(series);
|
||||
|
||||
var extraFile = Builder<OtherExtraFile>.CreateNew()
|
||||
.With(m => m.SeriesId = series.Id)
|
||||
.With(m => m.EpisodeFileId = 10)
|
||||
.BuildNew();
|
||||
|
||||
Db.Insert(extraFile);
|
||||
Subject.Clean();
|
||||
AllStoredModels.Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_delete_extra_files_that_have_a_coresponding_episode_file()
|
||||
{
|
||||
var series = Builder<Series>.CreateNew()
|
||||
.BuildNew();
|
||||
|
||||
var episodeFile = Builder<EpisodeFile>.CreateNew()
|
||||
.With(h => h.Quality = new QualityModel())
|
||||
.With(h => h.Languages = new List<Language> { Language.English })
|
||||
.BuildNew();
|
||||
|
||||
Db.Insert(series);
|
||||
Db.Insert(episodeFile);
|
||||
|
||||
var extraFile = Builder<OtherExtraFile>.CreateNew()
|
||||
.With(m => m.SeriesId = series.Id)
|
||||
.With(m => m.EpisodeFileId = episodeFile.Id)
|
||||
.BuildNew();
|
||||
|
||||
Db.Insert(extraFile);
|
||||
Subject.Clean();
|
||||
AllStoredModels.Should().HaveCount(1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_delete_extra_files_that_have_episodefileid_of_zero()
|
||||
{
|
||||
var series = Builder<Series>.CreateNew()
|
||||
.BuildNew();
|
||||
|
||||
Db.Insert(series);
|
||||
|
||||
var extraFile = Builder<OtherExtraFile>.CreateNew()
|
||||
.With(m => m.SeriesId = series.Id)
|
||||
.With(m => m.EpisodeFileId = 0)
|
||||
.BuildNew();
|
||||
|
||||
Db.Insert(extraFile);
|
||||
Subject.Clean();
|
||||
AllStoredModels.Should().HaveCount(0);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
using System.Collections.Generic;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Extras.Subtitles;
|
||||
using NzbDrone.Core.Housekeeping.Housekeepers;
|
||||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
|
||||
{
|
||||
[TestFixture]
|
||||
public class CleanupOrphanedSubtitleFilesFixture : DbTest<CleanupOrphanedSubtitleFiles, SubtitleFile>
|
||||
{
|
||||
[Test]
|
||||
public void should_delete_subtitle_files_that_dont_have_a_coresponding_series()
|
||||
{
|
||||
var episodeFile = Builder<EpisodeFile>.CreateNew()
|
||||
.With(h => h.Quality = new QualityModel())
|
||||
.With(h => h.Languages = new List<Language> { Language.English })
|
||||
.BuildNew();
|
||||
|
||||
Db.Insert(episodeFile);
|
||||
|
||||
var subtitleFile = Builder<SubtitleFile>.CreateNew()
|
||||
.With(m => m.EpisodeFileId = episodeFile.Id)
|
||||
.With(m => m.Language = Language.English)
|
||||
.BuildNew();
|
||||
|
||||
Db.Insert(subtitleFile);
|
||||
Subject.Clean();
|
||||
AllStoredModels.Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_delete_subtitle_files_that_have_a_coresponding_series()
|
||||
{
|
||||
var series = Builder<Series>.CreateNew()
|
||||
.BuildNew();
|
||||
|
||||
var episodeFile = Builder<EpisodeFile>.CreateNew()
|
||||
.With(h => h.Quality = new QualityModel())
|
||||
.With(h => h.Languages = new List<Language> { Language.English })
|
||||
.BuildNew();
|
||||
|
||||
Db.Insert(series);
|
||||
Db.Insert(episodeFile);
|
||||
|
||||
var subtitleFile = Builder<SubtitleFile>.CreateNew()
|
||||
.With(m => m.SeriesId = series.Id)
|
||||
.With(m => m.EpisodeFileId = episodeFile.Id)
|
||||
.With(m => m.Language = Language.English)
|
||||
.BuildNew();
|
||||
|
||||
Db.Insert(subtitleFile);
|
||||
Subject.Clean();
|
||||
AllStoredModels.Should().HaveCount(1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_delete_subtitle_files_that_dont_have_a_coresponding_episode_file()
|
||||
{
|
||||
var series = Builder<Series>.CreateNew()
|
||||
.BuildNew();
|
||||
|
||||
Db.Insert(series);
|
||||
|
||||
var subtitleFile = Builder<SubtitleFile>.CreateNew()
|
||||
.With(m => m.SeriesId = series.Id)
|
||||
.With(m => m.EpisodeFileId = 10)
|
||||
.With(m => m.Language = Language.English)
|
||||
.BuildNew();
|
||||
|
||||
Db.Insert(subtitleFile);
|
||||
Subject.Clean();
|
||||
AllStoredModels.Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_not_delete_subtitle_files_that_have_a_coresponding_episode_file()
|
||||
{
|
||||
var series = Builder<Series>.CreateNew()
|
||||
.BuildNew();
|
||||
|
||||
var episodeFile = Builder<EpisodeFile>.CreateNew()
|
||||
.With(h => h.Quality = new QualityModel())
|
||||
.With(h => h.Languages = new List<Language> { Language.English })
|
||||
.BuildNew();
|
||||
|
||||
Db.Insert(series);
|
||||
Db.Insert(episodeFile);
|
||||
|
||||
var subtitleFile = Builder<SubtitleFile>.CreateNew()
|
||||
.With(m => m.SeriesId = series.Id)
|
||||
.With(m => m.EpisodeFileId = episodeFile.Id)
|
||||
.With(m => m.Language = Language.English)
|
||||
.BuildNew();
|
||||
|
||||
Db.Insert(subtitleFile);
|
||||
Subject.Clean();
|
||||
AllStoredModels.Should().HaveCount(1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_delete_subtitle_files_that_have_episodefileid_of_zero()
|
||||
{
|
||||
var series = Builder<Series>.CreateNew()
|
||||
.BuildNew();
|
||||
|
||||
Db.Insert(series);
|
||||
|
||||
var subtitleFile = Builder<SubtitleFile>.CreateNew()
|
||||
.With(m => m.SeriesId = series.Id)
|
||||
.With(m => m.EpisodeFileId = 0)
|
||||
.With(m => m.Language = Language.English)
|
||||
.BuildNew();
|
||||
|
||||
Db.Insert(subtitleFile);
|
||||
Subject.Clean();
|
||||
AllStoredModels.Should().HaveCount(0);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
using Dapper;
|
||||
using NzbDrone.Core.Datastore;
|
||||
|
||||
namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
{
|
||||
public class CleanupOrphanedExtraFiles : IHousekeepingTask
|
||||
{
|
||||
private readonly IMainDatabase _database;
|
||||
|
||||
public CleanupOrphanedExtraFiles(IMainDatabase database)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
DeleteOrphanedBySeries();
|
||||
DeleteOrphanedByEpisodeFile();
|
||||
DeleteWhereEpisodeFileIsZero();
|
||||
}
|
||||
|
||||
private void DeleteOrphanedBySeries()
|
||||
{
|
||||
using var mapper = _database.OpenConnection();
|
||||
mapper.Execute(@"DELETE FROM ""ExtraFiles""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""ExtraFiles"".""Id"" FROM ""ExtraFiles""
|
||||
LEFT OUTER JOIN ""Series""
|
||||
ON ""ExtraFiles"".""SeriesId"" = ""Series"".""Id""
|
||||
WHERE ""Series"".""Id"" IS NULL)");
|
||||
}
|
||||
|
||||
private void DeleteOrphanedByEpisodeFile()
|
||||
{
|
||||
using var mapper = _database.OpenConnection();
|
||||
mapper.Execute(@"DELETE FROM ""ExtraFiles""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""ExtraFiles"".""Id"" FROM ""ExtraFiles""
|
||||
LEFT OUTER JOIN ""EpisodeFiles""
|
||||
ON ""ExtraFiles"".""EpisodeFileId"" = ""EpisodeFiles"".""Id""
|
||||
WHERE ""ExtraFiles"".""EpisodeFileId"" > 0
|
||||
AND ""EpisodeFiles"".""Id"" IS NULL)");
|
||||
}
|
||||
|
||||
private void DeleteWhereEpisodeFileIsZero()
|
||||
{
|
||||
using var mapper = _database.OpenConnection();
|
||||
mapper.Execute(@"DELETE FROM ""ExtraFiles""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""Id"" FROM ""ExtraFiles""
|
||||
WHERE ""EpisodeFileId"" = 0)");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
using Dapper;
|
||||
using NzbDrone.Core.Datastore;
|
||||
|
||||
namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||
{
|
||||
public class CleanupOrphanedSubtitleFiles : IHousekeepingTask
|
||||
{
|
||||
private readonly IMainDatabase _database;
|
||||
|
||||
public CleanupOrphanedSubtitleFiles(IMainDatabase database)
|
||||
{
|
||||
_database = database;
|
||||
}
|
||||
|
||||
public void Clean()
|
||||
{
|
||||
DeleteOrphanedBySeries();
|
||||
DeleteOrphanedByEpisodeFile();
|
||||
DeleteWhereEpisodeFileIsZero();
|
||||
}
|
||||
|
||||
private void DeleteOrphanedBySeries()
|
||||
{
|
||||
using var mapper = _database.OpenConnection();
|
||||
mapper.Execute(@"DELETE FROM ""SubtitleFiles""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""SubtitleFiles"".""Id"" FROM ""SubtitleFiles""
|
||||
LEFT OUTER JOIN ""Series""
|
||||
ON ""SubtitleFiles"".""SeriesId"" = ""Series"".""Id""
|
||||
WHERE ""Series"".""Id"" IS NULL)");
|
||||
}
|
||||
|
||||
private void DeleteOrphanedByEpisodeFile()
|
||||
{
|
||||
using var mapper = _database.OpenConnection();
|
||||
mapper.Execute(@"DELETE FROM ""SubtitleFiles""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""SubtitleFiles"".""Id"" FROM ""SubtitleFiles""
|
||||
LEFT OUTER JOIN ""EpisodeFiles""
|
||||
ON ""SubtitleFiles"".""EpisodeFileId"" = ""EpisodeFiles"".""Id""
|
||||
WHERE ""SubtitleFiles"".""EpisodeFileId"" > 0
|
||||
AND ""EpisodeFiles"".""Id"" IS NULL)");
|
||||
}
|
||||
|
||||
private void DeleteWhereEpisodeFileIsZero()
|
||||
{
|
||||
using var mapper = _database.OpenConnection();
|
||||
mapper.Execute(@"DELETE FROM ""SubtitleFiles""
|
||||
WHERE ""Id"" IN (
|
||||
SELECT ""Id"" FROM ""SubtitleFiles""
|
||||
WHERE ""EpisodeFileId"" = 0)");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue