From c9267757197c8dd642f3e5bdb8d496cab80c3d97 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Wed, 9 Oct 2013 23:58:56 -0700 Subject: [PATCH] Cleanup orphaned episode files if the series was deleted Fixed: Cleanup orphaned episode files after a series is deleted --- .../CleanupOrphanedEpisodeFilesFixture.cs | 45 +++++++++++++++++++ .../NzbDrone.Core.Test.csproj | 1 + .../CleanupOrphanedEpisodeFiles.cs | 31 +++++++++++++ src/NzbDrone.Core/NzbDrone.Core.csproj | 1 + 4 files changed, 78 insertions(+) create mode 100644 src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupOrphanedEpisodeFilesFixture.cs create mode 100644 src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedEpisodeFiles.cs diff --git a/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupOrphanedEpisodeFilesFixture.cs b/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupOrphanedEpisodeFilesFixture.cs new file mode 100644 index 000000000..0c97d0ae7 --- /dev/null +++ b/src/NzbDrone.Core.Test/Housekeeping/Housekeepers/CleanupOrphanedEpisodeFilesFixture.cs @@ -0,0 +1,45 @@ +using System.Linq; +using FizzWare.NBuilder; +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Core.Housekeeping.Housekeepers; +using NzbDrone.Core.MediaFiles; +using NzbDrone.Core.Test.Framework; +using NzbDrone.Core.Tv; + +namespace NzbDrone.Core.Test.Housekeeping.Housekeepers +{ + [TestFixture] + public class CleanupOrphanedEpisodeFilesFixture : DbTest + { + [Test] + public void should_delete_orphaned_episode_files() + { + var episodeFile = Builder.CreateNew() + .BuildNew(); + + Db.Insert(episodeFile); + Subject.Clean(); + AllStoredModels.Should().BeEmpty(); + } + + [Test] + public void should_not_delete_unorphaned_episode_files() + { + var episodeFiles = Builder.CreateListOfSize(2) + .BuildListOfNew(); + + Db.InsertMany(episodeFiles); + + var episode = Builder.CreateNew() + .With(e => e.EpisodeFileId = episodeFiles.First().Id) + .BuildNew(); + + Db.Insert(episode); + + Subject.Clean(); + AllStoredModels.Should().HaveCount(1); + Db.All().Should().Contain(e => e.EpisodeFileId == AllStoredModels.First().Id); + } + } +} diff --git a/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj index 4bdb919b9..98115ab31 100644 --- a/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -128,6 +128,7 @@ + diff --git a/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedEpisodeFiles.cs b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedEpisodeFiles.cs new file mode 100644 index 000000000..c11da71f1 --- /dev/null +++ b/src/NzbDrone.Core/Housekeeping/Housekeepers/CleanupOrphanedEpisodeFiles.cs @@ -0,0 +1,31 @@ +using NLog; +using NzbDrone.Core.Datastore; + +namespace NzbDrone.Core.Housekeeping.Housekeepers +{ + public class CleanupOrphanedEpisodeFiles : IHousekeepingTask + { + private readonly IDatabase _database; + private readonly Logger _logger; + + public CleanupOrphanedEpisodeFiles(IDatabase database, Logger logger) + { + _database = database; + _logger = logger; + } + + public void Clean() + { + _logger.Trace("Running orphaned episode files cleanup"); + + var mapper = _database.GetDataMapper(); + + mapper.ExecuteNonQuery(@"DELETE FROM EpisodeFiles + WHERE Id IN ( + SELECT EpisodeFiles.Id FROM EpisodeFiles + LEFT OUTER JOIN Episodes + ON EpisodeFiles.Id = Episodes.EpisodeFileId + WHERE Episodes.Id IS NULL)"); + } + } +} diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index 6c0c4bb3e..17c0af68b 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -228,6 +228,7 @@ +