Delete existing files on import if equal or better quality otherwise skip importing. If the folder is not deleted after processing it is renamed so it will not be processed repeatedly.

This commit is contained in:
Mark McDowall 2011-08-25 23:23:21 -07:00
parent 2ad200e743
commit d554e9ec83
3 changed files with 205 additions and 11 deletions

View File

@ -80,9 +80,6 @@ namespace NzbDrone.Core.Test
VerifyFileImport(result, mocker, fakeEpisode, size);
}
[TestCase("WEEDS.S03E01.DUAL.DVD.XviD.AC3.-HELLYWOOD.avi")]
[TestCase("WEEDS.S03E01.DUAL.SDTV.XviD.AC3.-HELLYWOOD.avi")]
public void import_new_file_episode_has_same_or_better_quality_should_skip(string fileName)
@ -116,7 +113,6 @@ namespace NzbDrone.Core.Test
VerifySkipImport(result, mocker);
}
[Test]
public void import_unparsable_file_should_skip()
{
@ -215,6 +211,186 @@ namespace NzbDrone.Core.Test
VerifySkipImport(result, mocker);
}
[TestCase("WEEDS.S03E01.DUAL.DVD.XviD.AC3.-HELLYWOOD.avi")]
[TestCase("WEEDS.S03E01.DUAL.bluray.x264.AC3.-HELLYWOOD.mkv")]
public void import_new_file_episode_has_better_quality_than_existing(string fileName)
{
//Fakes
var fakeSeries = Builder<Series>.CreateNew().Build();
var fakeEpisode = Builder<Episode>.CreateNew()
.With(c => c.EpisodeFile = Builder<EpisodeFile>.CreateNew()
.With(e => e.Quality = QualityTypes.SDTV).Build()
)
.Build();
//Mocks
var mocker = new AutoMoqer();
mocker.GetMock<DiskProvider>()
.Setup(e => e.GetSize(fileName)).Returns(12345).Verifiable();
mocker.GetMock<MediaFileProvider>()
.Setup(p => p.Exists(It.IsAny<String>()))
.Returns(false);
mocker.GetMock<EpisodeProvider>()
.Setup(e => e.GetEpisodesByParseResult(It.IsAny<EpisodeParseResult>(), false)).Returns(new List<Episode> { fakeEpisode });
//Act
var result = mocker.Resolve<DiskScanProvider>().ImportFile(fakeSeries, fileName);
//Assert
VerifyFileImport(result, mocker, fakeEpisode, 12345);
mocker.GetMock<DiskProvider>().Verify(p => p.DeleteFile(It.IsAny<string>()), Times.Once());
}
[TestCase("WEEDS.S03E01.DUAL.hdtv.XviD.AC3.-HELLYWOOD.avi")]
[TestCase("WEEDS.S03E01.DUAL.DVD.XviD.AC3.-HELLYWOOD.avi")]
[TestCase("WEEDS.S03E01.DUAL.bluray.x264.AC3.-HELLYWOOD.mkv")]
public void import_new_multi_part_file_episode_has_equal_or_better_quality_than_existing(string fileName)
{
//Fakes
var fakeSeries = Builder<Series>.CreateNew().Build();
var fakeEpisodes = Builder<Episode>.CreateListOfSize(2)
.WhereAll()
.Have(e => e.EpisodeFile = Builder<EpisodeFile>.CreateNew()
.With(f => f.Quality = QualityTypes.SDTV)
.Build())
.Build();
//Mocks
var mocker = new AutoMoqer();
mocker.GetMock<DiskProvider>()
.Setup(e => e.GetSize(fileName)).Returns(12345).Verifiable();
mocker.GetMock<MediaFileProvider>()
.Setup(p => p.Exists(It.IsAny<String>()))
.Returns(false);
mocker.GetMock<EpisodeProvider>()
.Setup(e => e.GetEpisodesByParseResult(It.IsAny<EpisodeParseResult>(), false)).Returns(fakeEpisodes);
//Act
var result = mocker.Resolve<DiskScanProvider>().ImportFile(fakeSeries, fileName);
//Assert
VerifyFileImport(result, mocker, fakeEpisodes[0], 12345);
mocker.GetMock<DiskProvider>().Verify(p => p.DeleteFile(It.IsAny<string>()), Times.Once());
}
[TestCase("WEEDS.S03E01.DUAL.DVD.XviD.AC3.-HELLYWOOD.avi")]
[TestCase("WEEDS.S03E01.DUAL.HDTV.XviD.AC3.-HELLYWOOD.avi")]
public void skip_import_new_multi_part_file_episode_existing_has_better_quality(string fileName)
{
//Fakes
var fakeSeries = Builder<Series>.CreateNew().Build();
var fakeEpisodes = Builder<Episode>.CreateListOfSize(2)
.WhereAll()
.Have(e => e.EpisodeFile = Builder<EpisodeFile>.CreateNew()
.With(f => f.Quality = QualityTypes.Bluray720p)
.Build())
.Build();
//Mocks
var mocker = new AutoMoqer();
mocker.GetMock<DiskProvider>()
.Setup(e => e.GetSize(fileName)).Returns(12345).Verifiable();
mocker.GetMock<MediaFileProvider>()
.Setup(p => p.Exists(It.IsAny<String>()))
.Returns(false);
mocker.GetMock<EpisodeProvider>()
.Setup(e => e.GetEpisodesByParseResult(It.IsAny<EpisodeParseResult>(), false)).Returns(fakeEpisodes);
//Act
var result = mocker.Resolve<DiskScanProvider>().ImportFile(fakeSeries, fileName);
//Assert
VerifySkipImport(result, mocker);
}
[Test]
public void import_new_multi_part_file_episode_replace_two_files()
{
const string fileName = "WEEDS.S03E01E02.DUAL.bluray.x264.AC3.-HELLYWOOD.mkv";
//Fakes
var fakeSeries = Builder<Series>.CreateNew().Build();
var fakeEpisodeFiles = Builder<EpisodeFile>.CreateListOfSize(2)
.WhereAll()
.Have(e => e.Quality = QualityTypes.SDTV)
.Build();
var fakeEpisode1 = Builder<Episode>.CreateNew()
.With(c => c.EpisodeFile = fakeEpisodeFiles[0])
.Build();
var fakeEpisode2 = Builder<Episode>.CreateNew()
.With(c => c.EpisodeFile = fakeEpisodeFiles[1])
.Build();
//Mocks
var mocker = new AutoMoqer();
mocker.GetMock<DiskProvider>()
.Setup(e => e.GetSize(fileName)).Returns(12345).Verifiable();
mocker.GetMock<MediaFileProvider>()
.Setup(p => p.Exists(It.IsAny<String>()))
.Returns(false);
mocker.GetMock<EpisodeProvider>()
.Setup(e => e.GetEpisodesByParseResult(It.IsAny<EpisodeParseResult>(), false)).Returns(new List<Episode> { fakeEpisode1, fakeEpisode2 });
//Act
var result = mocker.Resolve<DiskScanProvider>().ImportFile(fakeSeries, fileName);
//Assert
VerifyFileImport(result, mocker, fakeEpisode1, 12345);
mocker.GetMock<DiskProvider>().Verify(p => p.DeleteFile(It.IsAny<string>()), Times.Exactly(2));
}
[Test]
public void import_new_episode_no_existing_episode_file()
{
const string fileName = "WEEDS.S03E01E02.DUAL.bluray.x264.AC3.-HELLYWOOD.mkv";
//Fakes
var fakeSeries = Builder<Series>.CreateNew().Build();
var fakeEpisode = Builder<Episode>.CreateNew()
.With(e => e.EpisodeFileId = 0)
.With(e => e.EpisodeFile = null)
.Build();
//Mocks
var mocker = new AutoMoqer();
mocker.GetMock<DiskProvider>()
.Setup(e => e.GetSize(fileName)).Returns(12345).Verifiable();
mocker.GetMock<MediaFileProvider>()
.Setup(p => p.Exists(It.IsAny<String>()))
.Returns(false);
mocker.GetMock<EpisodeProvider>()
.Setup(e => e.GetEpisodesByParseResult(It.IsAny<EpisodeParseResult>(), false)).Returns(new List<Episode> { fakeEpisode});
//Act
var result = mocker.Resolve<DiskScanProvider>().ImportFile(fakeSeries, fileName);
//Assert
VerifyFileImport(result, mocker, fakeEpisode, 12345);
mocker.GetMock<DiskProvider>().Verify(p => p.DeleteFile(It.IsAny<string>()), Times.Never());
}
private static void VerifyFileImport(EpisodeFile result, AutoMoqer mocker, Episode fakeEpisode, int size)
{
mocker.VerifyAllMocks();
@ -236,6 +412,7 @@ namespace NzbDrone.Core.Test
result.Should().BeNull();
mocker.GetMock<MediaFileProvider>().Verify(p => p.Add(It.IsAny<EpisodeFile>()), Times.Never());
mocker.GetMock<EpisodeProvider>().Verify(p => p.UpdateEpisode(It.IsAny<Episode>()), Times.Never());
mocker.GetMock<DiskProvider>().Verify(p => p.DeleteFile(It.IsAny<string>()), Times.Never());
}
}
}

View File

@ -82,7 +82,6 @@ namespace NzbDrone.Core.Providers
return importedFiles;
}
public virtual EpisodeFile ImportFile(Series series, string filePath)
{
Logger.Trace("Importing file to database [{0}]", filePath);
@ -114,13 +113,22 @@ namespace NzbDrone.Core.Providers
if (episodes.Count <= 0)
{
Logger.Debug("Can't find any matching episodes in the database. skipping. {0}", filePath);
Logger.Debug("Can't find any matching episodes in the database. Skipping {0}", filePath);
return null;
}
if (episodes.Any(e => e.EpisodeFile != null && e.EpisodeFile.QualityWrapper > parseResult.Quality))
//Make sure this file is an upgrade for ALL episodes already on disk
if (episodes.All(e => e.EpisodeFile == null || e.EpisodeFile.QualityWrapper <= parseResult.Quality))
{
Logger.Trace("File with better quality is already attached. skipping {0}", filePath);
Logger.Debug("Deleting the existing file(s) on disk to upgrade to: {0}", filePath);
//Do the delete for files where there is already an episode on disk
episodes.Where(e => e.EpisodeFile != null).Select(e => e.EpisodeFile.Path).Distinct().ToList().ForEach(p => _diskProvider.DeleteFile(p));
}
else
{
//Skip this file because its not an upgrade
Logger.Trace("This file isn't an upgrade for all episodes. Skipping {0}", filePath);
return null;
}

View File

@ -73,6 +73,12 @@ namespace NzbDrone.Core.Providers.Jobs
continue;
}
if (subfolderInfo.Name.StartsWith("_NzbDrone_", StringComparison.CurrentCultureIgnoreCase))
{
Logger.Debug("Folder [{0}] is marked as already processedby NzbDrone. skipping.", subfolder);
continue;
}
//Parse the Folder name
var seriesName = Parser.ParseSeriesName(subfolderInfo.Name);
var series = _seriesProvider.FindSeries(seriesName);
@ -88,10 +94,13 @@ namespace NzbDrone.Core.Providers.Jobs
//Delete the folder only if folder is small enough
if (_diskProvider.GetDirectorySize(subfolder) < 10.Megabytes())
{
_diskProvider.DeleteFolder(subfolder, true);
}
//Otherwise rename the folder to say it was already processed once by NzbDrone so it will not be continually processed
else
_diskProvider.MoveDirectory(subfolderInfo.FullName, Path.Combine(subfolderInfo.Parent.FullName, "_NzbDrone_" + subfolderInfo.Name));
}
catch (Exception e)
{
Logger.ErrorException("An error has occurred while importing " + subfolder, e);
@ -99,4 +108,4 @@ namespace NzbDrone.Core.Providers.Jobs
}
}
}
}
}