mirror of
https://github.com/Radarr/Radarr.git
synced 2024-09-17 15:02:34 +02:00
Removed premove and instead check for source file being in use
This commit is contained in:
parent
a6e356c0cf
commit
a5e8452840
@ -5,7 +5,7 @@
|
|||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Test.Common;
|
using NzbDrone.Test.Common;
|
||||||
|
|
||||||
namespace NzbDrone.Common.Test
|
namespace NzbDrone.Common.Test.DiskProviderTests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class DiskProviderFixture : TestBase<DiskProvider>
|
public class DiskProviderFixture : TestBase<DiskProvider>
|
32
NzbDrone.Common.Test/DiskProviderTests/IsParentFixture.cs
Normal file
32
NzbDrone.Common.Test/DiskProviderTests/IsParentFixture.cs
Normal file
@ -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<DiskProvider>
|
||||||
|
{
|
||||||
|
[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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -62,6 +62,7 @@
|
|||||||
<Compile Include="CacheTests\CachedManagerFixture.cs" />
|
<Compile Include="CacheTests\CachedManagerFixture.cs" />
|
||||||
<Compile Include="CacheTests\CachedFixture.cs" />
|
<Compile Include="CacheTests\CachedFixture.cs" />
|
||||||
<Compile Include="ConfigFileProviderTest.cs" />
|
<Compile Include="ConfigFileProviderTest.cs" />
|
||||||
|
<Compile Include="DiskProviderTests\IsParentFixture.cs" />
|
||||||
<Compile Include="EnsureTest\PathExtensionFixture.cs" />
|
<Compile Include="EnsureTest\PathExtensionFixture.cs" />
|
||||||
<Compile Include="EnvironmentTests\StartupArgumentsFixture.cs" />
|
<Compile Include="EnvironmentTests\StartupArgumentsFixture.cs" />
|
||||||
<Compile Include="EnvironmentTests\EnvironmentProviderTest.cs" />
|
<Compile Include="EnvironmentTests\EnvironmentProviderTest.cs" />
|
||||||
@ -69,7 +70,7 @@
|
|||||||
<Compile Include="EventingTests\MessageAggregatorEventTests.cs" />
|
<Compile Include="EventingTests\MessageAggregatorEventTests.cs" />
|
||||||
<Compile Include="ReflectionExtensions.cs" />
|
<Compile Include="ReflectionExtensions.cs" />
|
||||||
<Compile Include="PathExtensionFixture.cs" />
|
<Compile Include="PathExtensionFixture.cs" />
|
||||||
<Compile Include="DiskProviderFixture.cs" />
|
<Compile Include="DiskProviderTests\DiskProviderFixture.cs" />
|
||||||
<Compile Include="EnvironmentProviderTest.cs" />
|
<Compile Include="EnvironmentProviderTest.cs" />
|
||||||
<Compile Include="ProcessProviderTests.cs" />
|
<Compile Include="ProcessProviderTests.cs" />
|
||||||
<Compile Include="ReflectionTests\ReflectionExtensionFixture.cs" />
|
<Compile Include="ReflectionTests\ReflectionExtensionFixture.cs" />
|
||||||
|
@ -39,7 +39,7 @@ public interface IDiskProvider
|
|||||||
bool IsFileLocked(FileInfo file);
|
bool IsFileLocked(FileInfo file);
|
||||||
string GetPathRoot(string path);
|
string GetPathRoot(string path);
|
||||||
void SetPermissions(string filename, string account, FileSystemRights rights, AccessControlType controlType);
|
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);
|
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);
|
parentPath = parentPath.TrimEnd(Path.DirectorySeparatorChar);
|
||||||
subfolder = subfolder.TrimEnd(Path.DirectorySeparatorChar);
|
childPath = childPath.TrimEnd(Path.DirectorySeparatorChar);
|
||||||
|
|
||||||
var diParent = new DirectoryInfo(parent);
|
var parent = new DirectoryInfo(parentPath);
|
||||||
var diSubfolder = new DirectoryInfo(subfolder);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
diSubfolder = diSubfolder.Parent;
|
child = child.Parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -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<NotInUseSpecification>
|
||||||
|
{
|
||||||
|
private LocalEpisode _localEpisode;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
_localEpisode = new LocalEpisode
|
||||||
|
{
|
||||||
|
Path = @"C:\Test\30 Rock\30.rock.s01e01.avi".AsOsAgnostic(),
|
||||||
|
Size = 100,
|
||||||
|
Series = Builder<Series>.CreateNew().Build()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenChildOfSeries()
|
||||||
|
{
|
||||||
|
Mocker.GetMock<IDiskProvider>()
|
||||||
|
.Setup(s => s.IsParent(_localEpisode.Series.Path, _localEpisode.Path))
|
||||||
|
.Returns(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenNewFile()
|
||||||
|
{
|
||||||
|
Mocker.GetMock<IDiskProvider>()
|
||||||
|
.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<IDiskProvider>()
|
||||||
|
.Verify(v => v.IsFileLocked(It.IsAny<FileInfo>()), Times.Never());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_false_if_file_is_in_use()
|
||||||
|
{
|
||||||
|
GivenNewFile();
|
||||||
|
|
||||||
|
Mocker.GetMock<IDiskProvider>()
|
||||||
|
.Setup(s => s.IsFileLocked(It.IsAny<FileInfo>()))
|
||||||
|
.Returns(true);
|
||||||
|
|
||||||
|
Subject.IsSatisfiedBy(_localEpisode).Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_true_if_file_is_not_in_use()
|
||||||
|
{
|
||||||
|
GivenNewFile();
|
||||||
|
|
||||||
|
Mocker.GetMock<IDiskProvider>()
|
||||||
|
.Setup(s => s.IsFileLocked(It.IsAny<FileInfo>()))
|
||||||
|
.Returns(false);
|
||||||
|
|
||||||
|
Subject.IsSatisfiedBy(_localEpisode).Should().BeTrue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -150,30 +150,5 @@ public void should_not_try_to_recyclebin_existing_file_if_file_doesnt_exist()
|
|||||||
|
|
||||||
Mocker.GetMock<IRecycleBinProvider>().Verify(v => v.DeleteFile(It.IsAny<string>()), Times.Never());
|
Mocker.GetMock<IRecycleBinProvider>().Verify(v => v.DeleteFile(It.IsAny<string>()), Times.Never());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void should_not_delete_file_if_pre_move_fails()
|
|
||||||
{
|
|
||||||
GivenSingleEpisodeWithSingleEpisodeFile();
|
|
||||||
|
|
||||||
Mocker.GetMock<IMoveEpisodeFiles>()
|
|
||||||
.Setup(s => s.PreMoveEpisodeFile(It.IsAny<EpisodeFile>(), It.IsAny<LocalEpisode>()))
|
|
||||||
.Throws<InvalidOperationException>();
|
|
||||||
|
|
||||||
Assert.Throws<InvalidOperationException>(() => Subject.UpgradeEpisodeFile(_episodeFile, _localEpisode));
|
|
||||||
|
|
||||||
Mocker.GetMock<IRecycleBinProvider>().Verify(v => v.DeleteFile(It.IsAny<string>()), Times.Never());
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void should_move_after_premove()
|
|
||||||
{
|
|
||||||
GivenSingleEpisodeWithSingleEpisodeFile();
|
|
||||||
|
|
||||||
Subject.UpgradeEpisodeFile(_episodeFile, _localEpisode);
|
|
||||||
|
|
||||||
Mocker.GetMock<IMoveEpisodeFiles>().Verify(v => v.PreMoveEpisodeFile(It.IsAny<EpisodeFile>(), It.IsAny<LocalEpisode>()), Times.Once());
|
|
||||||
Mocker.GetMock<IMoveEpisodeFiles>().Verify(v => v.MoveEpisodeFile(It.IsAny<EpisodeFile>(), It.IsAny<LocalEpisode>()), Times.Once());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,6 +129,7 @@
|
|||||||
<Compile Include="JobTests\TestJobs.cs" />
|
<Compile Include="JobTests\TestJobs.cs" />
|
||||||
<Compile Include="MediaCoverTests\CoverExistsSpecificationFixture.cs" />
|
<Compile Include="MediaCoverTests\CoverExistsSpecificationFixture.cs" />
|
||||||
<Compile Include="MediaCoverTests\MediaCoverServiceFixture.cs" />
|
<Compile Include="MediaCoverTests\MediaCoverServiceFixture.cs" />
|
||||||
|
<Compile Include="MediaFileTests\EpisodeImportTests\NotInUseSpecificationFixture.cs" />
|
||||||
<Compile Include="MediaFileTests\EpisodeImportTests\FreeSpaceSpecificationFixture.cs" />
|
<Compile Include="MediaFileTests\EpisodeImportTests\FreeSpaceSpecificationFixture.cs" />
|
||||||
<Compile Include="MediaFileTests\RenameEpisodeFileServiceFixture.cs" />
|
<Compile Include="MediaFileTests\RenameEpisodeFileServiceFixture.cs" />
|
||||||
<Compile Include="MediaFileTests\UpgradeMediaFileServiceFixture.cs" />
|
<Compile Include="MediaFileTests\UpgradeMediaFileServiceFixture.cs" />
|
||||||
|
@ -15,7 +15,6 @@ public interface IMoveEpisodeFiles
|
|||||||
{
|
{
|
||||||
EpisodeFile MoveEpisodeFile(EpisodeFile episodeFile, Series series);
|
EpisodeFile MoveEpisodeFile(EpisodeFile episodeFile, Series series);
|
||||||
EpisodeFile MoveEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode);
|
EpisodeFile MoveEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode);
|
||||||
EpisodeFile PreMoveEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MoveEpisodeFiles : IMoveEpisodeFiles
|
public class MoveEpisodeFiles : IMoveEpisodeFiles
|
||||||
@ -59,15 +58,6 @@ public EpisodeFile MoveEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEp
|
|||||||
return episodeFile;
|
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)
|
private EpisodeFile MoveFile(EpisodeFile episodeFile, string destinationFilename)
|
||||||
{
|
{
|
||||||
if (!_diskProvider.FileExists(episodeFile.Path))
|
if (!_diskProvider.FileExists(episodeFile.Path))
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -38,8 +38,6 @@ public EpisodeFile UpgradeEpisodeFile(EpisodeFile episodeFile, LocalEpisode loca
|
|||||||
.Select(e => e.EpisodeFile.Value)
|
.Select(e => e.EpisodeFile.Value)
|
||||||
.GroupBy(e => e.Id);
|
.GroupBy(e => e.Id);
|
||||||
|
|
||||||
episodeFile = _episodeFileMover.PreMoveEpisodeFile(episodeFile, localEpisode);
|
|
||||||
|
|
||||||
foreach (var existingFile in existingFiles)
|
foreach (var existingFile in existingFiles)
|
||||||
{
|
{
|
||||||
var file = existingFile.First();
|
var file = existingFile.First();
|
||||||
|
@ -224,6 +224,7 @@
|
|||||||
<Compile Include="MediaFiles\EpisodeImport\IImportDecisionEngineSpecification.cs" />
|
<Compile Include="MediaFiles\EpisodeImport\IImportDecisionEngineSpecification.cs" />
|
||||||
<Compile Include="MediaFiles\EpisodeImport\ImportDecisionMaker.cs" />
|
<Compile Include="MediaFiles\EpisodeImport\ImportDecisionMaker.cs" />
|
||||||
<Compile Include="MediaFiles\EpisodeImport\ImportApprovedEpisodes.cs" />
|
<Compile Include="MediaFiles\EpisodeImport\ImportApprovedEpisodes.cs" />
|
||||||
|
<Compile Include="MediaFiles\EpisodeImport\Specifications\NotInUseSpecification.cs" />
|
||||||
<Compile Include="MediaFiles\EpisodeImport\Specifications\FreeSpaceSpecification.cs" />
|
<Compile Include="MediaFiles\EpisodeImport\Specifications\FreeSpaceSpecification.cs" />
|
||||||
<Compile Include="MediaFiles\EpisodeImport\Specifications\NotExistingFileSpecification.cs" />
|
<Compile Include="MediaFiles\EpisodeImport\Specifications\NotExistingFileSpecification.cs" />
|
||||||
<Compile Include="MediaFiles\EpisodeImport\Specifications\UpgradeSpecification.cs" />
|
<Compile Include="MediaFiles\EpisodeImport\Specifications\UpgradeSpecification.cs" />
|
||||||
|
Loading…
Reference in New Issue
Block a user