diff --git a/NzbDrone.Core.Test/MediaFileTests/MediaFileTableCleanupServiceFixture.cs b/NzbDrone.Core.Test/MediaFileTests/MediaFileTableCleanupServiceFixture.cs index e0d022054..0b61e29d0 100644 --- a/NzbDrone.Core.Test/MediaFileTests/MediaFileTableCleanupServiceFixture.cs +++ b/NzbDrone.Core.Test/MediaFileTests/MediaFileTableCleanupServiceFixture.cs @@ -14,22 +14,27 @@ namespace NzbDrone.Core.Test.MediaFileTests { public class MediaFileTableCleanupServiceFixture : CoreTest { - private const string DeletedPath = "ANY FILE WITH THIS PATH IS CONSIDERED DELETED!"; + private const string DELETED_PATH = "ANY FILE WITH THIS PATH IS CONSIDERED DELETED!"; + private List _episodes; [SetUp] public void SetUp() { + _episodes = Builder.CreateListOfSize(10) + .Build() + .ToList(); + Mocker.GetMock() .Setup(s => s.GetSeries(It.IsAny())) .Returns(Builder.CreateNew().Build()); Mocker.GetMock() - .Setup(e => e.FileExists(It.Is(c => c != DeletedPath))) + .Setup(e => e.FileExists(It.Is(c => c != DELETED_PATH))) .Returns(true); Mocker.GetMock() - .Setup(c => c.GetEpisodesByFileId(It.IsAny())) - .Returns(new List {new Episode()}); + .Setup(c => c.GetEpisodeBySeries(It.IsAny())) + .Returns(_episodes); Mocker.GetMock() .Setup(s => s.IsParent(It.IsAny(), It.IsAny())) @@ -45,9 +50,11 @@ namespace NzbDrone.Core.Test.MediaFileTests private void GivenFilesAreNotAttachedToEpisode() { + _episodes.ForEach(e => e.EpisodeFileId = 0); + Mocker.GetMock() - .Setup(c => c.GetEpisodesByFileId(It.IsAny())) - .Returns(new List()); + .Setup(c => c.GetEpisodeBySeries(It.IsAny())) + .Returns(_episodes); } private void GivenFileIsNotInSeriesFolder() @@ -75,14 +82,14 @@ namespace NzbDrone.Core.Test.MediaFileTests { var episodeFiles = Builder.CreateListOfSize(10) .Random(2) - .With(c => c.Path = DeletedPath) + .With(c => c.Path = DELETED_PATH) .Build(); GivenEpisodeFiles(episodeFiles); Subject.Execute(new CleanMediaFileDb(0)); - Mocker.GetMock().Verify(c => c.Delete(It.Is(e => e.Path == DeletedPath), false), Times.Exactly(2)); + Mocker.GetMock().Verify(c => c.Delete(It.Is(e => e.Path == DELETED_PATH), false), Times.Exactly(2)); } [Test] @@ -116,5 +123,30 @@ namespace NzbDrone.Core.Test.MediaFileTests Mocker.GetMock().Verify(c => c.Delete(It.IsAny(), false), Times.Exactly(10)); } + + [Test] + public void should_unlink_episode_when_episodeFile_does_not_exist() + { + GivenEpisodeFiles(new List()); + + Subject.Execute(new CleanMediaFileDb(0)); + + Mocker.GetMock().Verify(c => c.UpdateEpisode(It.Is(e => e.EpisodeFileId == 0)), Times.Exactly(10)); + } + + [Test] + public void should_not_update_episode_when_episodeFile_exists() + { + var episodeFiles = Builder.CreateListOfSize(10) + .Random(10) + .With(c => c.Path = "ExistingPath") + .Build(); + + GivenEpisodeFiles(episodeFiles); + + Subject.Execute(new CleanMediaFileDb(0)); + + Mocker.GetMock().Verify(c => c.UpdateEpisode(It.IsAny()), Times.Never()); + } } } diff --git a/NzbDrone.Core/MediaFiles/MediaFileTableCleanupService.cs b/NzbDrone.Core/MediaFiles/MediaFileTableCleanupService.cs index fbeea2483..08b2bd868 100644 --- a/NzbDrone.Core/MediaFiles/MediaFileTableCleanupService.cs +++ b/NzbDrone.Core/MediaFiles/MediaFileTableCleanupService.cs @@ -16,21 +16,18 @@ namespace NzbDrone.Core.MediaFiles private readonly IDiskProvider _diskProvider; private readonly IEpisodeService _episodeService; private readonly ISeriesService _seriesService; - private readonly IParsingService _parsingService; private readonly Logger _logger; public MediaFileTableCleanupService(IMediaFileService mediaFileService, IDiskProvider diskProvider, IEpisodeService episodeService, ISeriesService seriesService, - IParsingService parsingService, Logger logger) { _mediaFileService = mediaFileService; _diskProvider = diskProvider; _episodeService = episodeService; _seriesService = seriesService; - _parsingService = parsingService; _logger = logger; } @@ -38,6 +35,7 @@ namespace NzbDrone.Core.MediaFiles { var seriesFile = _mediaFileService.GetFilesBySeries(message.SeriesId); var series = _seriesService.GetSeries(message.SeriesId); + var episodes = _episodeService.GetEpisodeBySeries(message.SeriesId); foreach (var episodeFile in seriesFile) { @@ -54,12 +52,10 @@ namespace NzbDrone.Core.MediaFiles { _logger.Trace("File [{0}] does not belong to this series, removing from db", episodeFile.Path); _mediaFileService.Delete(episodeFile); - continue; + continue; } - var episodes = _episodeService.GetEpisodesByFileId(episodeFile.Id); - - if (!episodes.Any()) + if (!episodes.Any(e => e.EpisodeFileId == episodeFile.Id)) { _logger.Trace("File [{0}] is not assigned to any episodes, removing from db", episodeFile.Path); _mediaFileService.Delete(episodeFile); @@ -75,12 +71,22 @@ namespace NzbDrone.Core.MediaFiles // continue; // } } + catch (Exception ex) { var errorMessage = String.Format("Unable to cleanup EpisodeFile in DB: {0}", episodeFile.Id); _logger.ErrorException(errorMessage, ex); } } + + foreach (var episode in episodes) + { + if (episode.EpisodeFileId > 0 && seriesFile.SingleOrDefault(f => f.Id == episode.EpisodeFileId) == null) + { + episode.EpisodeFileId = 0; + _episodeService.UpdateEpisode(episode); + } + } } } } \ No newline at end of file