From cbe4be814c165a2f4ea4290d6220613e6dfc8f29 Mon Sep 17 00:00:00 2001 From: "kay.one" Date: Sun, 12 May 2013 17:36:23 -0700 Subject: [PATCH] fixed diskscan removed all stored status fields from episode --- NzbDrone.Api/Commands/CommandModule.cs | 13 +-- NzbDrone.Common/Composition/Container.cs | 15 +++- .../Composition/ContainerBuilderBase.cs | 14 +-- NzbDrone.Common/Composition/IContainer.cs | 2 + .../UpgradeDiskSpecificationFixture.cs | 11 ++- NzbDrone.Core.Test/EpisodeStatusTest.cs | 90 +------------------ ...=> MediaFileTableCleanupServiceFixture.cs} | 34 ++++++- NzbDrone.Core.Test/NzbDrone.Core.Test.csproj | 3 +- .../GetVideoFilesFixture.cs | 1 + .../ImportFileFixture.cs | 32 +++++-- .../EpisodesBetweenDatesFixture.cs | 3 - .../EpisodesRepositoryReadFixture.cs | 45 ++++++++++ .../EpisodesWithoutFilesFixture.cs | 7 +- .../Datastore/Migration/Migration20130324.cs | 2 - .../Datastore/RelationshipExtensions.cs | 2 +- NzbDrone.Core/Datastore/TableMapping.cs | 7 +- .../UpgradeDiskSpecification.cs | 2 +- NzbDrone.Core/Jobs/TaskManager.cs | 8 +- .../MediaFiles/Commands/CleanMediaFileDb.cs | 14 +++ .../MediaFiles/Commands/DiskScanCommand.cs | 17 ++++ .../DiskScanService.cs} | 49 +++++++--- NzbDrone.Core/MediaFiles/EpisodeFile.cs | 14 --- .../MediaFiles/GhostFileCleanupService.cs | 48 ---------- .../MediaFileTableCleanupService.cs | 55 ++++++++++++ NzbDrone.Core/NzbDrone.Core.csproj | 6 +- .../Providers/Converting/HandbrakeProvider.cs | 2 +- NzbDrone.Core/Providers/MisnamedProvider.cs | 4 +- NzbDrone.Core/Tv/Episode.cs | 24 +---- NzbDrone.Core/Tv/EpisodeRepository.cs | 16 +--- NzbDrone.Core/Tv/EpisodeService.cs | 37 +------- NzbDrone/NLog.config | 2 +- UI/Series/Index/SeriesIndexLayout.js | 2 +- 32 files changed, 295 insertions(+), 286 deletions(-) rename NzbDrone.Core.Test/MediaFileTests/{GhostFileCleanupFixture.cs => MediaFileTableCleanupServiceFixture.cs} (57%) create mode 100644 NzbDrone.Core.Test/TvTests/EpisodeRepositoryTests/EpisodesRepositoryReadFixture.cs create mode 100644 NzbDrone.Core/MediaFiles/Commands/CleanMediaFileDb.cs create mode 100644 NzbDrone.Core/MediaFiles/Commands/DiskScanCommand.cs rename NzbDrone.Core/{Providers/IDiskScanService.cs => MediaFiles/DiskScanService.cs} (71%) delete mode 100644 NzbDrone.Core/MediaFiles/GhostFileCleanupService.cs create mode 100644 NzbDrone.Core/MediaFiles/MediaFileTableCleanupService.cs diff --git a/NzbDrone.Api/Commands/CommandModule.cs b/NzbDrone.Api/Commands/CommandModule.cs index ae99bb893..4db3b0f69 100644 --- a/NzbDrone.Api/Commands/CommandModule.cs +++ b/NzbDrone.Api/Commands/CommandModule.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using NzbDrone.Api.Extensions; +using NzbDrone.Common.Composition; using NzbDrone.Common.Messaging; namespace NzbDrone.Api.Commands @@ -9,20 +10,22 @@ namespace NzbDrone.Api.Commands public class CommandModule : NzbDroneRestModule { private readonly IMessageAggregator _messageAggregator; - private readonly IEnumerable _commands; + private readonly IContainer _container; - public CommandModule(IMessageAggregator messageAggregator, IEnumerable commands) + public CommandModule(IMessageAggregator messageAggregator, IContainer container) { _messageAggregator = messageAggregator; - _commands = commands; + _container = container; CreateResource = RunCommand; } private CommandResource RunCommand(CommandResource resource) { - var commandType = _commands.Single(c => c.GetType().Name.Replace("Command", "").Equals(resource.Command, StringComparison.InvariantCultureIgnoreCase)) - .GetType(); + var commandType = + _container.GetImplementations(typeof(ICommand)) + .Single(c => c.Name.Replace("Command", "") + .Equals(resource.Command, StringComparison.InvariantCultureIgnoreCase)); var command = Request.Body.FromJson(commandType); diff --git a/NzbDrone.Common/Composition/Container.cs b/NzbDrone.Common/Composition/Container.cs index 2033d3405..1afa9d3b6 100644 --- a/NzbDrone.Common/Composition/Container.cs +++ b/NzbDrone.Common/Composition/Container.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using TinyIoC; namespace NzbDrone.Common.Composition @@ -7,10 +8,12 @@ namespace NzbDrone.Common.Composition public class Container : IContainer { private readonly TinyIoCContainer _container; + private readonly List _loadedTypes; - public Container(TinyIoCContainer container) + public Container(TinyIoCContainer container, List loadedTypes) { _container = container; + _loadedTypes = loadedTypes; _container.Register(this); } @@ -92,5 +95,15 @@ namespace NzbDrone.Common.Composition { return _container.CanResolve(type); } + + public IEnumerable GetImplementations(Type contractType) + { + return _loadedTypes + .Where(implementation => + contractType.IsAssignableFrom(implementation) && + !implementation.IsInterface && + !implementation.IsAbstract + ); + } } } \ No newline at end of file diff --git a/NzbDrone.Common/Composition/ContainerBuilderBase.cs b/NzbDrone.Common/Composition/ContainerBuilderBase.cs index f48cc677a..14b6f6400 100644 --- a/NzbDrone.Common/Composition/ContainerBuilderBase.cs +++ b/NzbDrone.Common/Composition/ContainerBuilderBase.cs @@ -18,8 +18,6 @@ namespace NzbDrone.Common.Composition protected ContainerBuilderBase(params string[] assemblies) { - Container = new Container(new TinyIoCContainer()); - _loadedTypes = new List(); foreach (var assembly in assemblies) @@ -27,6 +25,7 @@ namespace NzbDrone.Common.Composition _loadedTypes.AddRange(Assembly.Load(assembly).GetTypes()); } + Container = new Container(new TinyIoCContainer(), _loadedTypes); AutoRegisterInterfaces(); } @@ -52,7 +51,7 @@ namespace NzbDrone.Common.Composition private void AutoRegisterImplementations(Type contractType) { - var implementations = GetImplementations(contractType).Where(c => !c.IsGenericTypeDefinition).ToList(); + var implementations = Container.GetImplementations(contractType).Where(c => !c.IsGenericTypeDefinition).ToList(); @@ -84,14 +83,5 @@ namespace NzbDrone.Common.Composition } } - private IEnumerable GetImplementations(Type contractType) - { - return _loadedTypes - .Where(implementation => - contractType.IsAssignableFrom(implementation) && - !implementation.IsInterface && - !implementation.IsAbstract - ); - } } } \ No newline at end of file diff --git a/NzbDrone.Common/Composition/IContainer.cs b/NzbDrone.Common/Composition/IContainer.cs index 7fc5dea09..f1b3c0001 100644 --- a/NzbDrone.Common/Composition/IContainer.cs +++ b/NzbDrone.Common/Composition/IContainer.cs @@ -26,5 +26,7 @@ namespace NzbDrone.Common.Composition void Register(Type registrationType, object instance); void RegisterAll(Type registrationType, IEnumerable implementationList); bool IsTypeRegistered(Type type); + + IEnumerable GetImplementations(Type contractType); } } \ No newline at end of file diff --git a/NzbDrone.Core.Test/DecisionEngineTests/UpgradeDiskSpecificationFixture.cs b/NzbDrone.Core.Test/DecisionEngineTests/UpgradeDiskSpecificationFixture.cs index f5d881db2..53d8dba97 100644 --- a/NzbDrone.Core.Test/DecisionEngineTests/UpgradeDiskSpecificationFixture.cs +++ b/NzbDrone.Core.Test/DecisionEngineTests/UpgradeDiskSpecificationFixture.cs @@ -34,8 +34,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests firstFile = new EpisodeFile { Quality = new QualityModel(Quality.Bluray1080p, true), DateAdded = DateTime.Now }; secondFile = new EpisodeFile { Quality = new QualityModel(Quality.Bluray1080p, true), DateAdded = DateTime.Now }; - var singleEpisodeList = new List { new Episode { EpisodeFile = firstFile }, new Episode { EpisodeFile = null } }; - var doubleEpisodeList = new List { new Episode { EpisodeFile = firstFile }, new Episode { EpisodeFile = secondFile }, new Episode { EpisodeFile = null } }; + var singleEpisodeList = new List { new Episode { EpisodeFile = firstFile, EpisodeFileId = 1 }, new Episode { EpisodeFile = null } }; + var doubleEpisodeList = new List { new Episode { EpisodeFile = firstFile, EpisodeFileId = 1 }, new Episode { EpisodeFile = secondFile, EpisodeFileId = 1 }, new Episode { EpisodeFile = null } }; var fakeSeries = Builder.CreateNew() .With(c => c.QualityProfile = new QualityProfile { Cutoff = Quality.Bluray1080p }) @@ -66,6 +66,13 @@ namespace NzbDrone.Core.Test.DecisionEngineTests secondFile.Quality = new QualityModel(Quality.SDTV); } + [Test] + public void should_return_true_if_episode_has_no_existing_file() + { + parseResultSingle.Episodes.ForEach(c => c.EpisodeFileId = 0); + _upgradeDisk.IsSatisfiedBy(parseResultSingle).Should().BeTrue(); + } + [Test] public void should_return_true_if_single_episode_doesnt_exist_on_disk() { diff --git a/NzbDrone.Core.Test/EpisodeStatusTest.cs b/NzbDrone.Core.Test/EpisodeStatusTest.cs index 8d266fe98..2b4d589f2 100644 --- a/NzbDrone.Core.Test/EpisodeStatusTest.cs +++ b/NzbDrone.Core.Test/EpisodeStatusTest.cs @@ -11,79 +11,15 @@ using NzbDrone.Core.Test.Framework; namespace NzbDrone.Core.Test { [TestFixture] - + public class EpisodeStatusTest : CoreTest { - [TestCase(1, false, false, EpisodeStatuses.NotAired)] - [TestCase(-2, false, false, EpisodeStatuses.Missing)] - [TestCase(0, false, false, EpisodeStatuses.AirsToday)] - [TestCase(1, true, false, EpisodeStatuses.Ready)] - public void no_grab_date(int offsetDays, bool hasEpisodes, bool ignored, EpisodeStatuses status) - { - Episode episode = Builder.CreateNew() - .With(e => e.AirDate = DateTime.Now.AddDays(offsetDays)) - .With(e => e.Ignored = ignored) - .With(e => e.GrabDate = null) - .Build(); - - if (hasEpisodes) - { - episode.EpisodeFile = new EpisodeFile(); - } - - episode.Status.Should().Be(status); - } - - [TestCase(1, false, false, EpisodeStatuses.Missing)] - [TestCase(-2, false, false, EpisodeStatuses.Missing)] - [TestCase(1, true, false, EpisodeStatuses.Ready)] - public void old_grab_date(int offsetDays, bool hasEpisodes, bool ignored, - EpisodeStatuses status) - { - Episode episode = Builder.CreateNew() - .With(e => e.Ignored = ignored) - .With(e => e.GrabDate = DateTime.Now.AddDays(-2).AddHours(-1)) - .With(e => e.AirDate = DateTime.Today.AddDays(-2)) - .Build(); - - if (hasEpisodes) - { - episode.EpisodeFile = new EpisodeFile(); - } - - episode.Status.Should().Be(status); - } - - [TestCase(1, false, false, EpisodeStatuses.Downloading)] - [TestCase(-2, false, false, EpisodeStatuses.Downloading)] - [TestCase(1, true, false, EpisodeStatuses.Ready)] - [TestCase(1, true, true, EpisodeStatuses.Ready)] - [TestCase(1, false, true, EpisodeStatuses.Downloading)] - public void recent_grab_date(int offsetDays, bool hasEpisodes, bool ignored, - EpisodeStatuses status) - { - Episode episode = Builder.CreateNew() - .With(e => e.AirDate = DateTime.Now.AddDays(offsetDays)) - .With(e => e.Ignored = ignored) - .With(e => e.GrabDate = DateTime.Now.AddHours(22)) - .Build(); - - if (hasEpisodes) - { - episode.EpisodeFile = new EpisodeFile(); - } - - episode.Status.Should().Be(status); - - } - [TestCase(1, true, true, EpisodeStatuses.Ready)] public void ignored_episode(int offsetDays, bool ignored, bool hasEpisodes, EpisodeStatuses status) { Episode episode = Builder.CreateNew() .With(e => e.AirDate = DateTime.Now.AddDays(offsetDays)) .With(e => e.Ignored = ignored) - .With(e => e.GrabDate = null) .Build(); if (hasEpisodes) @@ -101,33 +37,11 @@ namespace NzbDrone.Core.Test Episode episode = Builder.CreateNew() .With(e => e.AirDate = DateTime.Now.AddDays(20)) .With(e => e.Ignored = false) - .With(e => e.GrabDate = null) + .With(e => e.EpisodeFileId = 0) .Build(); episode.Status.Should().Be(EpisodeStatuses.NotAired); } - - [TestCase(false, false, EpisodeStatuses.Failed, PostDownloadStatusType.Failed)] - [TestCase(false, false, EpisodeStatuses.Unpacking, PostDownloadStatusType.Unpacking)] - [TestCase(true, false, EpisodeStatuses.Ready, PostDownloadStatusType.Failed)] - [TestCase(true, true, EpisodeStatuses.Ready, PostDownloadStatusType.Unpacking)] - public void episode_downloaded_post_download_status_is_used(bool hasEpisodes, bool ignored, - EpisodeStatuses status, PostDownloadStatusType postDownloadStatus) - { - Episode episode = Builder.CreateNew() - .With(e => e.Ignored = ignored) - .With(e => e.GrabDate = DateTime.Now.AddHours(22)) - .With(e => e.PostDownloadStatus = postDownloadStatus) - .Build(); - - if (hasEpisodes) - { - episode.EpisodeFile = new EpisodeFile(); - } - - episode.Status.Should().Be(status); - - } } } \ No newline at end of file diff --git a/NzbDrone.Core.Test/MediaFileTests/GhostFileCleanupFixture.cs b/NzbDrone.Core.Test/MediaFileTests/MediaFileTableCleanupServiceFixture.cs similarity index 57% rename from NzbDrone.Core.Test/MediaFileTests/GhostFileCleanupFixture.cs rename to NzbDrone.Core.Test/MediaFileTests/MediaFileTableCleanupServiceFixture.cs index b2617d87c..771f67540 100644 --- a/NzbDrone.Core.Test/MediaFileTests/GhostFileCleanupFixture.cs +++ b/NzbDrone.Core.Test/MediaFileTests/MediaFileTableCleanupServiceFixture.cs @@ -5,13 +5,14 @@ using Moq; using NUnit.Framework; using NzbDrone.Common; using NzbDrone.Core.MediaFiles; +using NzbDrone.Core.MediaFiles.Commands; using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Tv; using System.Linq; namespace NzbDrone.Core.Test.MediaFileTests { - public class GhostFileCleanupFixture : CoreTest + public class MediaFileTableCleanupServiceFixture : CoreTest { private void GiveEpisodeFiles(IEnumerable episodeFiles) @@ -30,6 +31,10 @@ namespace NzbDrone.Core.Test.MediaFileTests Mocker.GetMock() .Setup(e => e.FileExists(It.Is(c => c != DeletedPath))) .Returns(true); + + Mocker.GetMock() + .Setup(c => c.GetEpisodesByFileId(It.IsAny())) + .Returns(new List { new Episode() }); } [Test] @@ -40,7 +45,7 @@ namespace NzbDrone.Core.Test.MediaFileTests GiveEpisodeFiles(episodeFiles); - Subject.RemoveNonExistingFiles(0); + Subject.Execute(new CleanMediaFileDb(0)); Mocker.GetMock().Verify(c => c.UpdateEpisode(It.IsAny()), Times.Never()); } @@ -55,10 +60,33 @@ namespace NzbDrone.Core.Test.MediaFileTests GiveEpisodeFiles(episodeFiles); - Subject.RemoveNonExistingFiles(0); + Subject.Execute(new CleanMediaFileDb(0)); Mocker.GetMock().Verify(c => c.Delete(It.Is(e => e.Path == DeletedPath)), Times.Exactly(2)); } + + [Test] + public void should_delete_files_that_dont_belong_to_any_episodes() + { + var episodeFiles = Builder.CreateListOfSize(10) + .Random(10) + .With(c => c.Path = "ExistingPath") + .Build(); + + GiveEpisodeFiles(episodeFiles); + GivenFilesAreNotAttachedToEpisode(); + + Subject.Execute(new CleanMediaFileDb(0)); + + Mocker.GetMock().Verify(c => c.Delete(It.IsAny()), Times.Exactly(10)); + } + + private void GivenFilesAreNotAttachedToEpisode() + { + Mocker.GetMock() + .Setup(c => c.GetEpisodesByFileId(It.IsAny())) + .Returns(new List()); + } } } diff --git a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj index c6d206185..ada85977a 100644 --- a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -142,7 +142,7 @@ - + @@ -160,6 +160,7 @@ + diff --git a/NzbDrone.Core.Test/ProviderTests/DiskScanProviderTests/GetVideoFilesFixture.cs b/NzbDrone.Core.Test/ProviderTests/DiskScanProviderTests/GetVideoFilesFixture.cs index 976562756..5f9d1478c 100644 --- a/NzbDrone.Core.Test/ProviderTests/DiskScanProviderTests/GetVideoFilesFixture.cs +++ b/NzbDrone.Core.Test/ProviderTests/DiskScanProviderTests/GetVideoFilesFixture.cs @@ -4,6 +4,7 @@ using FluentAssertions; using Moq; using NUnit.Framework; using NzbDrone.Common; +using NzbDrone.Core.MediaFiles; using NzbDrone.Core.Providers; using NzbDrone.Core.Test.Framework; diff --git a/NzbDrone.Core.Test/ProviderTests/DiskScanProviderTests/ImportFileFixture.cs b/NzbDrone.Core.Test/ProviderTests/DiskScanProviderTests/ImportFileFixture.cs index ba45d0349..e3c9f513d 100644 --- a/NzbDrone.Core.Test/ProviderTests/DiskScanProviderTests/ImportFileFixture.cs +++ b/NzbDrone.Core.Test/ProviderTests/DiskScanProviderTests/ImportFileFixture.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Linq; using FizzWare.NBuilder; using FluentAssertions; @@ -23,7 +22,7 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskScanProviderTests private long _fileSize = 80.Megabytes(); private Series _fakeSeries; - private List _fakeEpisodes; + private Episode[] _fakeEpisodes; private Episode _fakeEpisode; [SetUp] @@ -35,14 +34,16 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskScanProviderTests _fakeEpisode = Builder .CreateNew() + .With(c => c.EpisodeFileId = 0) .Build(); _fakeEpisodes = Builder.CreateListOfSize(2) .All() .With(c => c.SeasonNumber = 3) + .With(c => c.EpisodeFileId = 1) .With(e => e.EpisodeFile = new EpisodeFile()) - .BuildList(); + .BuildList().ToArray(); GivenNewFile(); @@ -69,8 +70,20 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskScanProviderTests } - private void GivenEpisodes(IEnumerable episodes, QualityModel quality) + private void GivenEpisodes(Episode[] episodes, QualityModel quality) { + foreach (var episode in episodes) + { + if (episode.EpisodeFile == null) + { + episode.EpisodeFileId = 0; + } + else + { + episode.EpisodeFileId = episode.EpisodeFile.Value.Id; + } + } + Mocker.GetMock() .Setup(c => c.GetEpisodes(It.IsAny(), It.IsAny())) .Returns(new LocalEpisode @@ -102,6 +115,7 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskScanProviderTests public void import_new_file_with_same_quality_should_succeed() { _fakeEpisode.EpisodeFile = new EpisodeFile { Quality = new QualityModel(Quality.SDTV) }; + GivenEpisodes(new[] { _fakeEpisode }, new QualityModel(Quality.SDTV)); var result = Subject.ImportFile(_fakeSeries, "file.ext"); @@ -112,6 +126,7 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskScanProviderTests public void import_new_file_with_better_quality_should_succeed() { _fakeEpisode.EpisodeFile = new EpisodeFile { Quality = new QualityModel(Quality.SDTV) }; + GivenEpisodes(new[] { _fakeEpisode }, new QualityModel(Quality.HDTV1080p)); var result = Subject.ImportFile(_fakeSeries, "file.ext"); @@ -121,7 +136,8 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskScanProviderTests [Test] public void import_new_file_episode_has_better_quality_should_skip() { - _fakeEpisode.EpisodeFile = new EpisodeFile { Quality = new QualityModel(Quality.HDTV1080p) }; + _fakeEpisode.EpisodeFile = new EpisodeFile { Quality = new QualityModel(Quality.HDTV1080p), Id = 1 }; + GivenEpisodes(new[] { _fakeEpisode }, new QualityModel(Quality.SDTV)); var result = Subject.ImportFile(_fakeSeries, "file.ext"); @@ -158,7 +174,7 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskScanProviderTests [Test] public void import_file_with_no_episode_in_db_should_skip() { - GivenEpisodes(new List(), new QualityModel()); + GivenEpisodes(new Episode[0], new QualityModel()); var result = Subject.ImportFile(_fakeSeries, "file.ext"); @@ -185,8 +201,8 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskScanProviderTests [Test] public void skip_import_new_multi_part_file_episode_existing_has_better_quality() { - _fakeEpisodes[0].EpisodeFile = new EpisodeFile { Quality = new QualityModel(Quality.HDTV1080p) }; - _fakeEpisodes[1].EpisodeFile = new EpisodeFile { Quality = new QualityModel(Quality.HDTV1080p) }; + _fakeEpisodes[0].EpisodeFile = new EpisodeFile { Quality = new QualityModel(Quality.HDTV1080p), Id = 1 }; + _fakeEpisodes[1].EpisodeFile = new EpisodeFile { Quality = new QualityModel(Quality.HDTV1080p), Id = 1 }; GivenEpisodes(_fakeEpisodes, new QualityModel(Quality.SDTV)); diff --git a/NzbDrone.Core.Test/TvTests/EpisodeRepositoryTests/EpisodesBetweenDatesFixture.cs b/NzbDrone.Core.Test/TvTests/EpisodeRepositoryTests/EpisodesBetweenDatesFixture.cs index 5230fb6e5..b21b731d2 100644 --- a/NzbDrone.Core.Test/TvTests/EpisodeRepositoryTests/EpisodesBetweenDatesFixture.cs +++ b/NzbDrone.Core.Test/TvTests/EpisodeRepositoryTests/EpisodesBetweenDatesFixture.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using FizzWare.NBuilder; using FluentAssertions; using NUnit.Framework; diff --git a/NzbDrone.Core.Test/TvTests/EpisodeRepositoryTests/EpisodesRepositoryReadFixture.cs b/NzbDrone.Core.Test/TvTests/EpisodeRepositoryTests/EpisodesRepositoryReadFixture.cs new file mode 100644 index 000000000..41e691e34 --- /dev/null +++ b/NzbDrone.Core.Test/TvTests/EpisodeRepositoryTests/EpisodesRepositoryReadFixture.cs @@ -0,0 +1,45 @@ +using System; +using FizzWare.NBuilder; +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Core.MediaFiles; +using NzbDrone.Core.Test.Framework; +using NzbDrone.Core.Tv; + +namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests +{ + [TestFixture] + public class EpisodesRepositoryReadFixture : DbTest + { + private Series series; + + [SetUp] + public void Setup() + { + series = Builder.CreateNew() + .With(s => s.Runtime = 30) + .BuildNew(); + + Db.Insert(series); + } + + [Test] + public void should_get_episodes_by_file() + { + var episodeFile = Builder.CreateNew().BuildNew(); + + Db.Insert(episodeFile); + + var episode = Builder.CreateListOfSize(2) + .All() + .With(e => e.SeriesId = series.Id) + .With(e => e.EpisodeFileId = episodeFile.Id) + .BuildListOfNew(); + + Db.InsertMany(episode); + + var episodes = Subject.GetEpisodeByFileId(episodeFile.Id); + episodes.Should().HaveCount(2); + } + } +} diff --git a/NzbDrone.Core.Test/TvTests/EpisodeRepositoryTests/EpisodesWithoutFilesFixture.cs b/NzbDrone.Core.Test/TvTests/EpisodeRepositoryTests/EpisodesWithoutFilesFixture.cs index 082b9c4ff..12513c980 100644 --- a/NzbDrone.Core.Test/TvTests/EpisodeRepositoryTests/EpisodesWithoutFilesFixture.cs +++ b/NzbDrone.Core.Test/TvTests/EpisodeRepositoryTests/EpisodesWithoutFilesFixture.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Text; -using FizzWare.NBuilder; +using FizzWare.NBuilder; using FluentAssertions; using NUnit.Framework; using NzbDrone.Core.Datastore; diff --git a/NzbDrone.Core/Datastore/Migration/Migration20130324.cs b/NzbDrone.Core/Datastore/Migration/Migration20130324.cs index e5462aaa4..c0b5685bf 100644 --- a/NzbDrone.Core/Datastore/Migration/Migration20130324.cs +++ b/NzbDrone.Core/Datastore/Migration/Migration20130324.cs @@ -59,8 +59,6 @@ namespace NzbDrone.Core.Datastore.Migration .WithColumn("Ignored").AsBoolean().Nullable() .WithColumn("EpisodeFileId").AsInt32().Nullable() .WithColumn("AirDate").AsDateTime().Nullable() - .WithColumn("GrabDate").AsDateTime().Nullable() - .WithColumn("PostDownloadStatus").AsInt32().Nullable() .WithColumn("AbsoluteEpisodeNumber").AsInt32().Nullable() .WithColumn("SceneAbsoluteEpisodeNumber").AsInt32().Nullable() .WithColumn("SceneSeasonNumber").AsInt32().Nullable() diff --git a/NzbDrone.Core/Datastore/RelationshipExtensions.cs b/NzbDrone.Core/Datastore/RelationshipExtensions.cs index 7c8767966..1f32aee74 100644 --- a/NzbDrone.Core/Datastore/RelationshipExtensions.cs +++ b/NzbDrone.Core/Datastore/RelationshipExtensions.cs @@ -14,7 +14,7 @@ namespace NzbDrone.Core.Datastore { return relationshipBuilder.For(portalExpression.GetMemberName()) .LazyLoad((db, parent) => db.Query() - .Single(c => c.Id == childIdSelector(parent))); + .SingleOrDefault(c => c.Id == childIdSelector(parent))); } diff --git a/NzbDrone.Core/Datastore/TableMapping.cs b/NzbDrone.Core/Datastore/TableMapping.cs index fd05a11e6..239268e01 100644 --- a/NzbDrone.Core/Datastore/TableMapping.cs +++ b/NzbDrone.Core/Datastore/TableMapping.cs @@ -56,9 +56,12 @@ namespace NzbDrone.Core.Datastore Mapper.Entity().RegisterModel("Episodes") .Ignore(e => e.SeriesTitle) - .Relationships.AutoMapICollectionOrComplexProperties(); + .Relationship() + .HasOne(episode => episode.EpisodeFile, episode => episode.EpisodeFileId); + //.Relationships.AutoMapICollectionOrComplexProperties(); - Mapper.Entity().RegisterModel("EpisodeFiles"); + Mapper.Entity().RegisterModel("EpisodeFiles") + .Relationships.AutoMapICollectionOrComplexProperties(); Mapper.Entity().RegisterModel("QualityProfiles"); diff --git a/NzbDrone.Core/DecisionEngine/Specifications/UpgradeDiskSpecification.cs b/NzbDrone.Core/DecisionEngine/Specifications/UpgradeDiskSpecification.cs index db792e010..1134cedc9 100644 --- a/NzbDrone.Core/DecisionEngine/Specifications/UpgradeDiskSpecification.cs +++ b/NzbDrone.Core/DecisionEngine/Specifications/UpgradeDiskSpecification.cs @@ -26,7 +26,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications public virtual bool IsSatisfiedBy(RemoteEpisode subject) { - foreach (var file in subject.Episodes.Select(c => c.EpisodeFile).Where(c => c != null)) + foreach (var file in subject.Episodes.Where(c => c.EpisodeFileId != 0).Select(c => c.EpisodeFile.Value)) { _logger.Trace("Comparing file quality with report. Existing file is {0}", file.Quality); diff --git a/NzbDrone.Core/Jobs/TaskManager.cs b/NzbDrone.Core/Jobs/TaskManager.cs index fe82b7f21..16b06c9ba 100644 --- a/NzbDrone.Core/Jobs/TaskManager.cs +++ b/NzbDrone.Core/Jobs/TaskManager.cs @@ -69,8 +69,12 @@ namespace NzbDrone.Core.Jobs public void HandleAsync(CommandExecutedEvent message) { - var commandId = _scheduledTaskRepository.GetDefinition(message.Command.GetType()).Id; - _scheduledTaskRepository.SetLastExecutionTime(commandId, DateTime.UtcNow); + var scheduledTask = _scheduledTaskRepository.All().SingleOrDefault(c => c.TypeName == message.Command.GetType().FullName); + + if (scheduledTask != null) + { + _scheduledTaskRepository.SetLastExecutionTime(scheduledTask.Id, DateTime.UtcNow); + } } } } \ No newline at end of file diff --git a/NzbDrone.Core/MediaFiles/Commands/CleanMediaFileDb.cs b/NzbDrone.Core/MediaFiles/Commands/CleanMediaFileDb.cs new file mode 100644 index 000000000..b873dcc5f --- /dev/null +++ b/NzbDrone.Core/MediaFiles/Commands/CleanMediaFileDb.cs @@ -0,0 +1,14 @@ +using NzbDrone.Common.Messaging; + +namespace NzbDrone.Core.MediaFiles.Commands +{ + public class CleanMediaFileDb : ICommand + { + public int SeriesId { get; private set; } + + public CleanMediaFileDb(int seriesId) + { + SeriesId = seriesId; + } + } +} \ No newline at end of file diff --git a/NzbDrone.Core/MediaFiles/Commands/DiskScanCommand.cs b/NzbDrone.Core/MediaFiles/Commands/DiskScanCommand.cs new file mode 100644 index 000000000..db7dd7a04 --- /dev/null +++ b/NzbDrone.Core/MediaFiles/Commands/DiskScanCommand.cs @@ -0,0 +1,17 @@ +using NzbDrone.Common.Messaging; + +namespace NzbDrone.Core.MediaFiles.Commands +{ + public class DiskScanCommand : ICommand + { + public int? SeriesId { get; private set; } + + public DiskScanCommand(int seriesId = 0) + { + if (seriesId != 0) + { + SeriesId = seriesId; + } + } + } +} \ No newline at end of file diff --git a/NzbDrone.Core/Providers/IDiskScanService.cs b/NzbDrone.Core/MediaFiles/DiskScanService.cs similarity index 71% rename from NzbDrone.Core/Providers/IDiskScanService.cs rename to NzbDrone.Core/MediaFiles/DiskScanService.cs index 2d7ab8364..2ea1f5c4c 100644 --- a/NzbDrone.Core/Providers/IDiskScanService.cs +++ b/NzbDrone.Core/MediaFiles/DiskScanService.cs @@ -4,40 +4,43 @@ using System.IO; using System.Linq; using NLog; using NzbDrone.Common; -using NzbDrone.Core.MediaFiles; +using NzbDrone.Common.Messaging; +using NzbDrone.Core.MediaFiles.Commands; using NzbDrone.Core.Parser; +using NzbDrone.Core.Providers; using NzbDrone.Core.Tv; -namespace NzbDrone.Core.Providers +namespace NzbDrone.Core.MediaFiles { public interface IDiskScanService { - void Scan(Series series); EpisodeFile ImportFile(Series series, string filePath); string[] GetVideoFiles(string path, bool allDirectories = true); } - public class DiskScanService : IDiskScanService + public class DiskScanService : IDiskScanService, IExecute { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); private static readonly string[] MediaExtensions = new[] { ".mkv", ".avi", ".wmv", ".mp4", ".mpg", ".mpeg", ".xvid", ".flv", ".mov", ".rm", ".rmvb", ".divx", ".dvr-ms", ".ts", ".ogm", ".m4v", ".strm" }; private readonly IDiskProvider _diskProvider; - private readonly ICleanGhostFiles _ghostFileCleaner; + private readonly ISeriesService _seriesService; private readonly IMediaFileService _mediaFileService; private readonly IVideoFileInfoReader _videoFileInfoReader; private readonly IParsingService _parsingService; + private readonly IMessageAggregator _messageAggregator; - public DiskScanService(IDiskProvider diskProvider, ICleanGhostFiles ghostFileCleaner, IMediaFileService mediaFileService, IVideoFileInfoReader videoFileInfoReader, - IParsingService parsingService) + public DiskScanService(IDiskProvider diskProvider, ISeriesService seriesService, IMediaFileService mediaFileService, IVideoFileInfoReader videoFileInfoReader, + IParsingService parsingService, IMessageAggregator messageAggregator) { _diskProvider = diskProvider; - _ghostFileCleaner = ghostFileCleaner; + _seriesService = seriesService; _mediaFileService = mediaFileService; _videoFileInfoReader = videoFileInfoReader; _parsingService = parsingService; + _messageAggregator = messageAggregator; } - public virtual void Scan(Series series) + private void Scan(Series series) { if (!_diskProvider.FolderExists(series.Path)) { @@ -45,7 +48,7 @@ namespace NzbDrone.Core.Providers return; } - _ghostFileCleaner.RemoveNonExistingFiles(series.Id); + _messageAggregator.PublishCommand(new CleanMediaFileDb(series.Id)); var mediaFileList = GetVideoFiles(series.Path); @@ -58,7 +61,7 @@ namespace NzbDrone.Core.Providers //Todo: Move the episode linking to here, instead of import (or rename import) } - public virtual EpisodeFile ImportFile(Series series, string filePath) + public EpisodeFile ImportFile(Series series, string filePath) { Logger.Trace("Importing file to database [{0}]", filePath); @@ -87,7 +90,7 @@ namespace NzbDrone.Core.Providers } } - if (parsedEpisode.Episodes.Any(e => e.EpisodeFile != null && e.EpisodeFile.Quality > parsedEpisode.Quality)) + if (parsedEpisode.Episodes.Any(e => e.EpisodeFileId != 0 && e.EpisodeFile.Value.Quality > parsedEpisode.Quality)) { Logger.Trace("This file isn't an upgrade for all episodes. Skipping {0}", filePath); return null; @@ -101,6 +104,7 @@ namespace NzbDrone.Core.Providers episodeFile.Quality = parsedEpisode.Quality; episodeFile.SeasonNumber = parsedEpisode.SeasonNumber; episodeFile.SceneName = Path.GetFileNameWithoutExtension(filePath.CleanPath()); + episodeFile.Episodes = parsedEpisode.Episodes; //Todo: We shouldn't actually import the file until we confirm its the only one we want. //Todo: Separate episodeFile creation from importing (pass file to import to import) @@ -108,7 +112,7 @@ namespace NzbDrone.Core.Providers return episodeFile; } - public virtual string[] GetVideoFiles(string path, bool allDirectories = true) + public string[] GetVideoFiles(string path, bool allDirectories = true) { Logger.Debug("Scanning '{0}' for video files", path); @@ -120,5 +124,24 @@ namespace NzbDrone.Core.Providers Logger.Trace("{0} video files were found in {1}", mediaFileList.Count, path); return mediaFileList.ToArray(); } + + public void Execute(DiskScanCommand message) + { + var seriesToScan = new List(); + + if (message.SeriesId.HasValue) + { + seriesToScan.Add(_seriesService.GetSeries(message.SeriesId.Value)); + } + else + { + seriesToScan.AddRange(_seriesService.GetAllSeries()); + } + + foreach (var series in seriesToScan) + { + Scan(series); + } + } } } \ No newline at end of file diff --git a/NzbDrone.Core/MediaFiles/EpisodeFile.cs b/NzbDrone.Core/MediaFiles/EpisodeFile.cs index 72c7d1598..b95b3e1e5 100644 --- a/NzbDrone.Core/MediaFiles/EpisodeFile.cs +++ b/NzbDrone.Core/MediaFiles/EpisodeFile.cs @@ -6,20 +6,6 @@ namespace NzbDrone.Core.MediaFiles { public class EpisodeFile : ModelBase { - public EpisodeFile() - { - - } - - public EpisodeFile(EpisodeFile source) - { - Id = source.Id; - SeriesId = source.SeriesId; - SeasonNumber = source.SeasonNumber; - Path = source.Path; - Size = source.Size; - } - public int SeriesId { get; set; } public int SeasonNumber { get; set; } public string Path { get; set; } diff --git a/NzbDrone.Core/MediaFiles/GhostFileCleanupService.cs b/NzbDrone.Core/MediaFiles/GhostFileCleanupService.cs deleted file mode 100644 index efbca4182..000000000 --- a/NzbDrone.Core/MediaFiles/GhostFileCleanupService.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using NLog; -using NzbDrone.Common; - -namespace NzbDrone.Core.MediaFiles -{ - public interface ICleanGhostFiles - { - void RemoveNonExistingFiles(int seriesId); - } - - - public class GhostFileCleanupService : ICleanGhostFiles - { - private readonly IMediaFileService _mediaFileService; - private readonly IDiskProvider _diskProvider; - private readonly Logger _logger; - - public GhostFileCleanupService(IMediaFileService mediaFileService, IDiskProvider diskProvider, Logger logger) - { - _mediaFileService = mediaFileService; - _diskProvider = diskProvider; - _logger = logger; - } - - public void RemoveNonExistingFiles(int seriesId) - { - var seriesFile = _mediaFileService.GetFilesBySeries(seriesId); - - foreach (var episodeFile in seriesFile) - { - try - { - if (!_diskProvider.FileExists(episodeFile.Path)) - { - _logger.Trace("File [{0}] no longer exists on disk. removing from db", episodeFile.Path); - _mediaFileService.Delete(episodeFile); - } - } - catch (Exception ex) - { - var message = String.Format("Unable to cleanup EpisodeFile in DB: {0}", episodeFile.Id); - _logger.ErrorException(message, ex); - } - } - } - } -} \ No newline at end of file diff --git a/NzbDrone.Core/MediaFiles/MediaFileTableCleanupService.cs b/NzbDrone.Core/MediaFiles/MediaFileTableCleanupService.cs new file mode 100644 index 000000000..949f88679 --- /dev/null +++ b/NzbDrone.Core/MediaFiles/MediaFileTableCleanupService.cs @@ -0,0 +1,55 @@ +using System; +using System.Linq; +using NLog; +using NzbDrone.Common; +using NzbDrone.Common.Messaging; +using NzbDrone.Core.MediaFiles.Commands; +using NzbDrone.Core.Tv; + +namespace NzbDrone.Core.MediaFiles +{ + + public class MediaFileTableCleanupService : IExecute + { + private readonly IMediaFileService _mediaFileService; + private readonly IDiskProvider _diskProvider; + private readonly IEpisodeService _episodeService; + private readonly Logger _logger; + + public MediaFileTableCleanupService(IMediaFileService mediaFileService, IDiskProvider diskProvider, IEpisodeService episodeService, Logger logger) + { + _mediaFileService = mediaFileService; + _diskProvider = diskProvider; + _episodeService = episodeService; + _logger = logger; + } + + public void Execute(CleanMediaFileDb message) + { + var seriesFile = _mediaFileService.GetFilesBySeries(message.SeriesId); + + foreach (var episodeFile in seriesFile) + { + try + { + if (!_diskProvider.FileExists(episodeFile.Path)) + { + _logger.Trace("File [{0}] no longer exists on disk. removing from db", episodeFile.Path); + _mediaFileService.Delete(episodeFile); + } + + if (!_episodeService.GetEpisodesByFileId(episodeFile.Id).Any()) + { + _logger.Trace("File [{0}] is not assigned to any episodes. removing from db", episodeFile.Path); + _mediaFileService.Delete(episodeFile); + } + } + catch (Exception ex) + { + var errorMessage = String.Format("Unable to cleanup EpisodeFile in DB: {0}", episodeFile.Id); + _logger.ErrorException(errorMessage, ex); + } + } + } + } +} \ No newline at end of file diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index 0de65433b..08de40cd8 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -247,7 +247,9 @@ + + @@ -296,7 +298,7 @@ - + @@ -404,7 +406,7 @@ Code - + Code diff --git a/NzbDrone.Core/Providers/Converting/HandbrakeProvider.cs b/NzbDrone.Core/Providers/Converting/HandbrakeProvider.cs index d2209c324..6fd7eca30 100644 --- a/NzbDrone.Core/Providers/Converting/HandbrakeProvider.cs +++ b/NzbDrone.Core/Providers/Converting/HandbrakeProvider.cs @@ -40,7 +40,7 @@ namespace NzbDrone.Core.Providers.Converting var outputFile = _configService.GetValue("iPodConvertDir", ""); var handBrakePreset = _configService.GetValue("HandBrakePreset", "iPhone & iPod Touch"); - var handBrakeCommand = String.Format("-i \"{0}\" -o \"{1}\" --preset=\"{2}\"", episode.EpisodeFile.Path, outputFile, handBrakePreset); + var handBrakeCommand = String.Format("-i \"{0}\" -o \"{1}\" --preset=\"{2}\"", episode.EpisodeFile.Value.Path, outputFile, handBrakePreset); var handBrakeFile = @"C:\Program Files (x86)\Handbrake\HandBrakeCLI.exe"; try diff --git a/NzbDrone.Core/Providers/MisnamedProvider.cs b/NzbDrone.Core/Providers/MisnamedProvider.cs index bb80443a4..fb20010c1 100644 --- a/NzbDrone.Core/Providers/MisnamedProvider.cs +++ b/NzbDrone.Core/Providers/MisnamedProvider.cs @@ -30,7 +30,7 @@ namespace NzbDrone.Core.Providers var misnamedFilesSelect = episodesWithFiles.AsParallel().Where( w => - w.First().EpisodeFile.Path != + w.First().EpisodeFile.Value.Path != _buildFileNames.BuildFilename(w.Select(e => e).ToList(), w.First().Series, w.First().EpisodeFile)).Skip(Math.Max(pageSize * (pageNumber - 1), 0)).Take(pageSize); //Process the episodes @@ -41,7 +41,7 @@ namespace NzbDrone.Core.Providers var properName = _buildFileNames.BuildFilename(episodes, firstEpisode.Series, firstEpisode.EpisodeFile); - var currentName = Path.GetFileNameWithoutExtension(firstEpisode.EpisodeFile.Path); + var currentName = Path.GetFileNameWithoutExtension(firstEpisode.EpisodeFile.Value.Path); if (properName != currentName) { diff --git a/NzbDrone.Core/Tv/Episode.cs b/NzbDrone.Core/Tv/Episode.cs index cce3045b7..cb70473bb 100644 --- a/NzbDrone.Core/Tv/Episode.cs +++ b/NzbDrone.Core/Tv/Episode.cs @@ -1,4 +1,5 @@ using System; +using Marr.Data; using NzbDrone.Core.Datastore; using NzbDrone.Core.MediaFiles; using NzbDrone.Core.Model; @@ -18,38 +19,21 @@ namespace NzbDrone.Core.Tv public string Overview { get; set; } public Boolean Ignored { get; set; } - public PostDownloadStatusType PostDownloadStatus { get; set; } public Nullable AbsoluteEpisodeNumber { get; set; } public int SceneSeasonNumber { get; set; } public int SceneEpisodeNumber { get; set; } - public DateTime? GrabDate { get; set; } public bool HasFile { - get { return EpisodeFile != null; } + get { return EpisodeFileId != 0; } } - + public EpisodeStatuses Status { get { if (HasFile) return EpisodeStatuses.Ready; - if (GrabDate != null) - { - if (PostDownloadStatus == PostDownloadStatusType.Unpacking) - return EpisodeStatuses.Unpacking; - - if (PostDownloadStatus == PostDownloadStatusType.Failed) - return EpisodeStatuses.Failed; - - if (GrabDate.Value.AddDays(1) >= DateTime.Now) - return EpisodeStatuses.Downloading; - } - - if (GrabDate != null && GrabDate.Value.AddDays(1) >= DateTime.Now) - return EpisodeStatuses.Downloading; - if (AirDate != null && AirDate.Value.Date == DateTime.Today) return EpisodeStatuses.AirsToday; @@ -75,7 +59,7 @@ namespace NzbDrone.Core.Tv public Series Series { get; set; } - public EpisodeFile EpisodeFile { get; set; } + public LazyLoaded EpisodeFile { get; set; } public override string ToString() { diff --git a/NzbDrone.Core/Tv/EpisodeRepository.cs b/NzbDrone.Core/Tv/EpisodeRepository.cs index 9d5727caf..3372960a4 100644 --- a/NzbDrone.Core/Tv/EpisodeRepository.cs +++ b/NzbDrone.Core/Tv/EpisodeRepository.cs @@ -1,10 +1,6 @@ using System; using System.Collections.Generic; -using System.ComponentModel; -using System.Data; -using System.Diagnostics; using System.Linq; -using FluentMigrator.Runner; using Marr.Data; using Marr.Data.QGen; using NzbDrone.Common.Messaging; @@ -26,7 +22,6 @@ namespace NzbDrone.Core.Tv List EpisodesWithFiles(); List EpisodesBetweenDates(DateTime startDate, DateTime endDate); void SetIgnoreFlat(Episode episode, bool ignoreFlag); - void SetPostDownloadStatus(int episodeId, PostDownloadStatusType status); void SetFileId(int episodeId, int fileId); } @@ -62,7 +57,7 @@ namespace NzbDrone.Core.Tv public List GetEpisodeByFileId(int fileId) { - return Query.Where(s => s.EpisodeFile != null && s.EpisodeFile.Id == fileId).ToList(); + return Query.Where(e => e.EpisodeFileId == fileId).ToList(); } public PagingSpec EpisodesWithoutFiles(PagingSpec pagingSpec, bool includeSpecials) @@ -74,7 +69,7 @@ namespace NzbDrone.Core.Tv { startingSeasonNumber = 0; } - + var pagingQuery = Query.Join(JoinType.Inner, e => e.Series, (e, s) => e.SeriesId == s.Id) .Where(e => e.EpisodeFileId == 0) .AndWhere(e => e.SeasonNumber >= startingSeasonNumber) @@ -98,7 +93,7 @@ namespace NzbDrone.Core.Tv public List EpisodesWithFiles() { - return Query.Where(s => s.EpisodeFile != null).ToList(); + return Query.Where(s => s.EpisodeFileId != 0).ToList(); } public List EpisodesBetweenDates(DateTime startDate, DateTime endDate) @@ -113,11 +108,6 @@ namespace NzbDrone.Core.Tv SetFields(episode, p => p.Ignored); } - public void SetPostDownloadStatus(int episodeId, PostDownloadStatusType status) - { - SetFields(new Episode { Id = episodeId, PostDownloadStatus = status }, episode => episode.PostDownloadStatus); - } - public void SetFileId(int episodeId, int fileId) { SetFields(new Episode { Id = episodeId, EpisodeFileId = fileId }, episode => episode.EpisodeFileId); diff --git a/NzbDrone.Core/Tv/EpisodeService.cs b/NzbDrone.Core/Tv/EpisodeService.cs index ca69afbde..c3e9f0549 100644 --- a/NzbDrone.Core/Tv/EpisodeService.cs +++ b/NzbDrone.Core/Tv/EpisodeService.cs @@ -29,16 +29,14 @@ namespace NzbDrone.Core.Tv List GetEpisodeNumbersBySeason(int seriesId, int seasonNumber); void SetEpisodeIgnore(int episodeId, bool isIgnored); bool IsFirstOrLastEpisodeOfSeason(int episodeId); - void SetPostDownloadStatus(List episodeIds, PostDownloadStatusType postDownloadStatus); void UpdateEpisodes(List episodes); List EpisodesBetweenDates(DateTime start, DateTime end); } public class EpisodeService : IEpisodeService, - IHandle, IHandle, IHandle, - IHandleAsync, + IHandleAsync, IHandleAsync { @@ -166,7 +164,7 @@ namespace NzbDrone.Core.Tv episodeToUpdate.EpisodeFileId > 0) { logger.Info("Unlinking episode file because TheTVDB changed the episode number..."); - episodeToUpdate.EpisodeFile = null; + episodeToUpdate.EpisodeFileId = 0; } episodeToUpdate.SeriesId = series.Id; @@ -268,22 +266,6 @@ namespace NzbDrone.Core.Tv return false; } - public void SetPostDownloadStatus(List episodeIds, PostDownloadStatusType postDownloadStatus) - { - if (episodeIds.Count == 0) throw new ArgumentException("episodeIds should contain one or more episode ids."); - - - foreach (var episodeId in episodeIds) - { - var episode = _episodeRepository.Get(episodeId); - episode.PostDownloadStatus = postDownloadStatus; - _episodeRepository.Update(episode); - } - - - logger.Trace("Updating PostDownloadStatus for {0} episode(s) to {1}", episodeIds.Count, postDownloadStatus); - } - public void UpdateEpisodes(List episodes) { _episodeRepository.UpdateMany(episodes); @@ -296,16 +278,6 @@ namespace NzbDrone.Core.Tv return LinkSeriesToEpisodes(episodes); } - public void Handle(EpisodeGrabbedEvent message) - { - foreach (var episode in message.Episode.Episodes) - { - logger.Trace("Marking episode {0} as fetched.", episode.Id); - episode.GrabDate = DateTime.UtcNow; - _episodeRepository.Update(episode); - } - } - public void HandleAsync(SeriesDeletedEvent message) { var episodes = GetEpisodeBySeries(message.Series.Id); @@ -317,10 +289,8 @@ namespace NzbDrone.Core.Tv foreach (var episode in GetEpisodesByFileId(message.EpisodeFile.Id)) { _logger.Trace("Detaching episode {0} from file.", episode.Id); - episode.EpisodeFile = null; + episode.EpisodeFileId = 0; episode.Ignored = _configService.AutoIgnorePreviouslyDownloadedEpisodes; - episode.GrabDate = null; - episode.PostDownloadStatus = PostDownloadStatusType.Unknown; UpdateEpisode(episode); } } @@ -335,7 +305,6 @@ namespace NzbDrone.Core.Tv foreach (var episode in message.EpisodeFile.Episodes.Value) { _episodeRepository.SetFileId(episode.Id, message.EpisodeFile.Id); - _episodeRepository.SetPostDownloadStatus(episode.Id, PostDownloadStatusType.NoError); _logger.Debug("Linking [{0}] > [{1}]", message.EpisodeFile.Path, episode); } } diff --git a/NzbDrone/NLog.config b/NzbDrone/NLog.config index 23f2d521e..6ed2d7f88 100644 --- a/NzbDrone/NLog.config +++ b/NzbDrone/NLog.config @@ -25,7 +25,7 @@ layout="${date:format=yy-M-d HH\:mm\:ss.f}|${logger}}|${level}|${message}|${exception:format=ToString}"/> - + diff --git a/UI/Series/Index/SeriesIndexLayout.js b/UI/Series/Index/SeriesIndexLayout.js index 7f0c19700..018aadabc 100644 --- a/UI/Series/Index/SeriesIndexLayout.js +++ b/UI/Series/Index/SeriesIndexLayout.js @@ -156,7 +156,7 @@ define([ { title : 'Update Library', icon : 'icon-refresh', - command : 'updatelibrary', + command : 'diskscan', successMessage: 'Library was updated!', errorMessage : 'Library update failed!' },