From a5e84528405a30eb061f65528aa1e05fe185930b Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Sun, 11 Aug 2013 15:55:26 -0700 Subject: [PATCH] Removed premove and instead check for source file being in use --- .../DiskProviderFixture.cs | 2 +- .../DiskProviderTests/IsParentFixture.cs | 32 +++++++ .../NzbDrone.Common.Test.csproj | 3 +- NzbDrone.Common/DiskProvider.cs | 18 ++-- .../NotInUseSpecificationFixture.cs | 92 +++++++++++++++++++ .../UpgradeMediaFileServiceFixture.cs | 25 ----- NzbDrone.Core.Test/NzbDrone.Core.Test.csproj | 1 + .../MediaFiles/EpisodeFileMovingService.cs | 10 -- .../Specifications/NotInUseSpecification.cs | 40 ++++++++ .../MediaFiles/UpgradeMediaFileService.cs | 2 - NzbDrone.Core/NzbDrone.Core.csproj | 1 + 11 files changed, 178 insertions(+), 48 deletions(-) rename NzbDrone.Common.Test/{ => DiskProviderTests}/DiskProviderFixture.cs (99%) create mode 100644 NzbDrone.Common.Test/DiskProviderTests/IsParentFixture.cs create mode 100644 NzbDrone.Core.Test/MediaFileTests/EpisodeImportTests/NotInUseSpecificationFixture.cs create mode 100644 NzbDrone.Core/MediaFiles/EpisodeImport/Specifications/NotInUseSpecification.cs diff --git a/NzbDrone.Common.Test/DiskProviderFixture.cs b/NzbDrone.Common.Test/DiskProviderTests/DiskProviderFixture.cs similarity index 99% rename from NzbDrone.Common.Test/DiskProviderFixture.cs rename to NzbDrone.Common.Test/DiskProviderTests/DiskProviderFixture.cs index 8e2102ec7..435e953ce 100644 --- a/NzbDrone.Common.Test/DiskProviderFixture.cs +++ b/NzbDrone.Common.Test/DiskProviderTests/DiskProviderFixture.cs @@ -5,7 +5,7 @@ using NUnit.Framework; using NzbDrone.Test.Common; -namespace NzbDrone.Common.Test +namespace NzbDrone.Common.Test.DiskProviderTests { [TestFixture] public class DiskProviderFixture : TestBase diff --git a/NzbDrone.Common.Test/DiskProviderTests/IsParentFixture.cs b/NzbDrone.Common.Test/DiskProviderTests/IsParentFixture.cs new file mode 100644 index 000000000..0dcd77a30 --- /dev/null +++ b/NzbDrone.Common.Test/DiskProviderTests/IsParentFixture.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Test.Common; + +namespace NzbDrone.Common.Test.DiskProviderTests +{ + [TestFixture] + public class IsParentFixture : TestBase + { + [Test] + public void should_return_false_when_not_a_child() + { + Subject.IsParent(@"C:\Test", @"C:\Another Folder").Should().BeFalse(); + } + + [Test] + public void should_return_true_when_folder_is_parent_of_another_folder() + { + Subject.IsParent(@"C:\Test", @"C:\Test\TV").Should().BeTrue(); + } + + [Test] + public void should_return_true_when_folder_is_parent_of_a_file() + { + Subject.IsParent(@"C:\Test", @"C:\Test\30.Rock.S01E01.Pilot.avi").Should().BeTrue(); + } + } +} diff --git a/NzbDrone.Common.Test/NzbDrone.Common.Test.csproj b/NzbDrone.Common.Test/NzbDrone.Common.Test.csproj index dc7dd87d3..1dd3ccd78 100644 --- a/NzbDrone.Common.Test/NzbDrone.Common.Test.csproj +++ b/NzbDrone.Common.Test/NzbDrone.Common.Test.csproj @@ -62,6 +62,7 @@ + @@ -69,7 +70,7 @@ - + diff --git a/NzbDrone.Common/DiskProvider.cs b/NzbDrone.Common/DiskProvider.cs index cf88f96f3..e83dc8e1a 100644 --- a/NzbDrone.Common/DiskProvider.cs +++ b/NzbDrone.Common/DiskProvider.cs @@ -39,7 +39,7 @@ public interface IDiskProvider bool IsFileLocked(FileInfo file); string GetPathRoot(string path); void SetPermissions(string filename, string account, FileSystemRights rights, AccessControlType controlType); - bool IsParent(string parentfolder, string subfolder); + bool IsParent(string parentPath, string childPath); FileAttributes GetFileAttributes(string path); } @@ -429,22 +429,22 @@ public void SetPermissions(string filename, string account, FileSystemRights rig } - public bool IsParent(string parent, string subfolder) + public bool IsParent(string parentPath, string childPath) { - parent = parent.TrimEnd(Path.DirectorySeparatorChar); - subfolder = subfolder.TrimEnd(Path.DirectorySeparatorChar); + parentPath = parentPath.TrimEnd(Path.DirectorySeparatorChar); + childPath = childPath.TrimEnd(Path.DirectorySeparatorChar); - var diParent = new DirectoryInfo(parent); - var diSubfolder = new DirectoryInfo(subfolder); + var parent = new DirectoryInfo(parentPath); + var child = new DirectoryInfo(childPath); - while (diSubfolder.Parent != null) + while (child.Parent != null) { - if (diSubfolder.Parent.FullName == diParent.FullName) + if (child.Parent.FullName == parent.FullName) { return true; } - diSubfolder = diSubfolder.Parent; + child = child.Parent; } return false; diff --git a/NzbDrone.Core.Test/MediaFileTests/EpisodeImportTests/NotInUseSpecificationFixture.cs b/NzbDrone.Core.Test/MediaFileTests/EpisodeImportTests/NotInUseSpecificationFixture.cs new file mode 100644 index 000000000..98080014b --- /dev/null +++ b/NzbDrone.Core.Test/MediaFileTests/EpisodeImportTests/NotInUseSpecificationFixture.cs @@ -0,0 +1,92 @@ +using System.IO; +using System.Linq; +using FizzWare.NBuilder; +using FluentAssertions; +using Marr.Data; +using Moq; +using Newtonsoft.Json.Serialization; +using NUnit.Framework; +using NzbDrone.Common; +using NzbDrone.Core.MediaFiles; +using NzbDrone.Core.MediaFiles.EpisodeImport.Specifications; +using NzbDrone.Core.Parser.Model; +using NzbDrone.Core.Test.Framework; +using NzbDrone.Core.Tv; +using NzbDrone.Test.Common; + +namespace NzbDrone.Core.Test.MediaFileTests.EpisodeImportTests +{ + [TestFixture] + public class NotInUseSpecificationFixture : CoreTest + { + private LocalEpisode _localEpisode; + + [SetUp] + public void Setup() + { + _localEpisode = new LocalEpisode + { + Path = @"C:\Test\30 Rock\30.rock.s01e01.avi".AsOsAgnostic(), + Size = 100, + Series = Builder.CreateNew().Build() + }; + } + + private void GivenChildOfSeries() + { + Mocker.GetMock() + .Setup(s => s.IsParent(_localEpisode.Series.Path, _localEpisode.Path)) + .Returns(true); + } + + private void GivenNewFile() + { + Mocker.GetMock() + .Setup(s => s.IsParent(_localEpisode.Series.Path, _localEpisode.Path)) + .Returns(false); + } + + [Test] + public void should_return_true_if_file_is_under_series_folder() + { + GivenChildOfSeries(); + + Subject.IsSatisfiedBy(_localEpisode).Should().BeTrue(); + } + + [Test] + public void should_not_check_for_file_in_use_if_child_of_series_folder() + { + GivenChildOfSeries(); + + Subject.IsSatisfiedBy(_localEpisode); + + Mocker.GetMock() + .Verify(v => v.IsFileLocked(It.IsAny()), Times.Never()); + } + + [Test] + public void should_return_false_if_file_is_in_use() + { + GivenNewFile(); + + Mocker.GetMock() + .Setup(s => s.IsFileLocked(It.IsAny())) + .Returns(true); + + Subject.IsSatisfiedBy(_localEpisode).Should().BeFalse(); + } + + [Test] + public void should_return_true_if_file_is_not_in_use() + { + GivenNewFile(); + + Mocker.GetMock() + .Setup(s => s.IsFileLocked(It.IsAny())) + .Returns(false); + + Subject.IsSatisfiedBy(_localEpisode).Should().BeTrue(); + } + } +} diff --git a/NzbDrone.Core.Test/MediaFileTests/UpgradeMediaFileServiceFixture.cs b/NzbDrone.Core.Test/MediaFileTests/UpgradeMediaFileServiceFixture.cs index f8cfc020e..210eaff99 100644 --- a/NzbDrone.Core.Test/MediaFileTests/UpgradeMediaFileServiceFixture.cs +++ b/NzbDrone.Core.Test/MediaFileTests/UpgradeMediaFileServiceFixture.cs @@ -150,30 +150,5 @@ public void should_not_try_to_recyclebin_existing_file_if_file_doesnt_exist() Mocker.GetMock().Verify(v => v.DeleteFile(It.IsAny()), Times.Never()); } - - [Test] - public void should_not_delete_file_if_pre_move_fails() - { - GivenSingleEpisodeWithSingleEpisodeFile(); - - Mocker.GetMock() - .Setup(s => s.PreMoveEpisodeFile(It.IsAny(), It.IsAny())) - .Throws(); - - Assert.Throws(() => Subject.UpgradeEpisodeFile(_episodeFile, _localEpisode)); - - Mocker.GetMock().Verify(v => v.DeleteFile(It.IsAny()), Times.Never()); - } - - [Test] - public void should_move_after_premove() - { - GivenSingleEpisodeWithSingleEpisodeFile(); - - Subject.UpgradeEpisodeFile(_episodeFile, _localEpisode); - - Mocker.GetMock().Verify(v => v.PreMoveEpisodeFile(It.IsAny(), It.IsAny()), Times.Once()); - Mocker.GetMock().Verify(v => v.MoveEpisodeFile(It.IsAny(), It.IsAny()), Times.Once()); - } } } diff --git a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj index 7f4ecd66d..0cfb64c94 100644 --- a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -129,6 +129,7 @@ + diff --git a/NzbDrone.Core/MediaFiles/EpisodeFileMovingService.cs b/NzbDrone.Core/MediaFiles/EpisodeFileMovingService.cs index a23670442..a8dd667be 100644 --- a/NzbDrone.Core/MediaFiles/EpisodeFileMovingService.cs +++ b/NzbDrone.Core/MediaFiles/EpisodeFileMovingService.cs @@ -15,7 +15,6 @@ public interface IMoveEpisodeFiles { EpisodeFile MoveEpisodeFile(EpisodeFile episodeFile, Series series); EpisodeFile MoveEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode); - EpisodeFile PreMoveEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode); } public class MoveEpisodeFiles : IMoveEpisodeFiles @@ -59,15 +58,6 @@ public EpisodeFile MoveEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEp return episodeFile; } - public EpisodeFile PreMoveEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode) - { - var newFileName = Path.GetFileNameWithoutExtension(episodeFile.Path); - var destinationFilename = _buildFileNames.BuildFilePath(localEpisode.Series, localEpisode.SeasonNumber, newFileName, Path.GetExtension(episodeFile.Path)); - episodeFile = MoveFile(episodeFile, destinationFilename); - - return episodeFile; - } - private EpisodeFile MoveFile(EpisodeFile episodeFile, string destinationFilename) { if (!_diskProvider.FileExists(episodeFile.Path)) diff --git a/NzbDrone.Core/MediaFiles/EpisodeImport/Specifications/NotInUseSpecification.cs b/NzbDrone.Core/MediaFiles/EpisodeImport/Specifications/NotInUseSpecification.cs new file mode 100644 index 000000000..32d1a1cee --- /dev/null +++ b/NzbDrone.Core/MediaFiles/EpisodeImport/Specifications/NotInUseSpecification.cs @@ -0,0 +1,40 @@ +using System.IO; +using System.Linq; +using NLog; +using NzbDrone.Common; +using NzbDrone.Core.Parser.Model; +using NzbDrone.Core.Tv; + +namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications +{ + public class NotInUseSpecification : IImportDecisionEngineSpecification + { + private readonly IDiskProvider _diskProvider; + private readonly Logger _logger; + + public NotInUseSpecification(IDiskProvider diskProvider, Logger logger) + { + _diskProvider = diskProvider; + _logger = logger; + } + + public string RejectionReason { get { return "File is in use"; } } + + public bool IsSatisfiedBy(LocalEpisode localEpisode) + { + if (_diskProvider.IsParent(localEpisode.Series.Path, localEpisode.Path)) + { + _logger.Trace("{0} is in series folder, skipping in use check", localEpisode.Path); + return true; + } + + if (_diskProvider.IsFileLocked(new FileInfo(localEpisode.Path))) + { + _logger.Trace("{0} is in use"); + return false; + } + + return true; + } + } +} diff --git a/NzbDrone.Core/MediaFiles/UpgradeMediaFileService.cs b/NzbDrone.Core/MediaFiles/UpgradeMediaFileService.cs index 480c45457..c272e9197 100644 --- a/NzbDrone.Core/MediaFiles/UpgradeMediaFileService.cs +++ b/NzbDrone.Core/MediaFiles/UpgradeMediaFileService.cs @@ -38,8 +38,6 @@ public EpisodeFile UpgradeEpisodeFile(EpisodeFile episodeFile, LocalEpisode loca .Select(e => e.EpisodeFile.Value) .GroupBy(e => e.Id); - episodeFile = _episodeFileMover.PreMoveEpisodeFile(episodeFile, localEpisode); - foreach (var existingFile in existingFiles) { var file = existingFile.First(); diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index ada5b62e4..12c61a20d 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -224,6 +224,7 @@ +