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.

pull/2/head
Mark McDowall 13 years ago
parent 2ad200e743
commit d554e9ec83

@ -80,9 +80,6 @@ namespace NzbDrone.Core.Test
VerifyFileImport(result, mocker, fakeEpisode, size); VerifyFileImport(result, mocker, fakeEpisode, size);
} }
[TestCase("WEEDS.S03E01.DUAL.DVD.XviD.AC3.-HELLYWOOD.avi")] [TestCase("WEEDS.S03E01.DUAL.DVD.XviD.AC3.-HELLYWOOD.avi")]
[TestCase("WEEDS.S03E01.DUAL.SDTV.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) 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); VerifySkipImport(result, mocker);
} }
[Test] [Test]
public void import_unparsable_file_should_skip() public void import_unparsable_file_should_skip()
{ {
@ -215,6 +211,186 @@ namespace NzbDrone.Core.Test
VerifySkipImport(result, mocker); 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) private static void VerifyFileImport(EpisodeFile result, AutoMoqer mocker, Episode fakeEpisode, int size)
{ {
mocker.VerifyAllMocks(); mocker.VerifyAllMocks();
@ -236,6 +412,7 @@ namespace NzbDrone.Core.Test
result.Should().BeNull(); result.Should().BeNull();
mocker.GetMock<MediaFileProvider>().Verify(p => p.Add(It.IsAny<EpisodeFile>()), Times.Never()); 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<EpisodeProvider>().Verify(p => p.UpdateEpisode(It.IsAny<Episode>()), Times.Never());
mocker.GetMock<DiskProvider>().Verify(p => p.DeleteFile(It.IsAny<string>()), Times.Never());
} }
} }
} }

@ -82,7 +82,6 @@ namespace NzbDrone.Core.Providers
return importedFiles; return importedFiles;
} }
public virtual EpisodeFile ImportFile(Series series, string filePath) public virtual EpisodeFile ImportFile(Series series, string filePath)
{ {
Logger.Trace("Importing file to database [{0}]", filePath); Logger.Trace("Importing file to database [{0}]", filePath);
@ -114,13 +113,22 @@ namespace NzbDrone.Core.Providers
if (episodes.Count <= 0) 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; 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.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
{ {
Logger.Trace("File with better quality is already attached. skipping {0}", filePath); //Skip this file because its not an upgrade
Logger.Trace("This file isn't an upgrade for all episodes. Skipping {0}", filePath);
return null; return null;
} }

@ -73,6 +73,12 @@ namespace NzbDrone.Core.Providers.Jobs
continue; 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 //Parse the Folder name
var seriesName = Parser.ParseSeriesName(subfolderInfo.Name); var seriesName = Parser.ParseSeriesName(subfolderInfo.Name);
var series = _seriesProvider.FindSeries(seriesName); var series = _seriesProvider.FindSeries(seriesName);
@ -88,10 +94,13 @@ namespace NzbDrone.Core.Providers.Jobs
//Delete the folder only if folder is small enough //Delete the folder only if folder is small enough
if (_diskProvider.GetDirectorySize(subfolder) < 10.Megabytes()) if (_diskProvider.GetDirectorySize(subfolder) < 10.Megabytes())
{
_diskProvider.DeleteFolder(subfolder, true); _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) catch (Exception e)
{ {
Logger.ErrorException("An error has occurred while importing " + subfolder, e); Logger.ErrorException("An error has occurred while importing " + subfolder, e);

Loading…
Cancel
Save