From 83370ddbbb43d27c14899dcbcfe8a2a2cce00fa1 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Wed, 29 Mar 2017 06:44:50 -0700 Subject: [PATCH] New: Episode files sent to Recycling Bin are put into subfolders Closes #401 --- src/NzbDrone.Api/EpisodeFiles/EpisodeFileModule.cs | 8 +++++++- .../MediaFiles/UpgradeMediaFileServiceFixture.cs | 8 ++++---- .../RecycleBinProviderTests/DeleteFileFixture.cs | 12 ++++++++++++ src/NzbDrone.Core/Extras/Files/ExtraFileService.cs | 4 +++- src/NzbDrone.Core/MediaFiles/RecycleBinProvider.cs | 13 ++++++++----- .../MediaFiles/UpgradeMediaFileService.cs | 4 +++- 6 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/NzbDrone.Api/EpisodeFiles/EpisodeFileModule.cs b/src/NzbDrone.Api/EpisodeFiles/EpisodeFileModule.cs index 0271ae218..c2044bda3 100644 --- a/src/NzbDrone.Api/EpisodeFiles/EpisodeFileModule.cs +++ b/src/NzbDrone.Api/EpisodeFiles/EpisodeFileModule.cs @@ -2,6 +2,8 @@ using System.IO; using NLog; using NzbDrone.Api.REST; +using NzbDrone.Common.Disk; +using NzbDrone.Common.Extensions; using NzbDrone.Core.Datastore.Events; using NzbDrone.Core.MediaFiles; using NzbDrone.Core.MediaFiles.Events; @@ -16,6 +18,7 @@ namespace NzbDrone.Api.EpisodeFiles IHandle { private readonly IMediaFileService _mediaFileService; + private readonly IDiskProvider _diskProvider; private readonly IRecycleBinProvider _recycleBinProvider; private readonly ISeriesService _seriesService; private readonly IQualityUpgradableSpecification _qualityUpgradableSpecification; @@ -23,6 +26,7 @@ namespace NzbDrone.Api.EpisodeFiles public EpisodeFileModule(IBroadcastSignalRMessage signalRBroadcaster, IMediaFileService mediaFileService, + IDiskProvider diskProvider, IRecycleBinProvider recycleBinProvider, ISeriesService seriesService, IQualityUpgradableSpecification qualityUpgradableSpecification, @@ -30,6 +34,7 @@ namespace NzbDrone.Api.EpisodeFiles : base(signalRBroadcaster) { _mediaFileService = mediaFileService; + _diskProvider = diskProvider; _recycleBinProvider = recycleBinProvider; _seriesService = seriesService; _qualityUpgradableSpecification = qualityUpgradableSpecification; @@ -74,9 +79,10 @@ namespace NzbDrone.Api.EpisodeFiles var episodeFile = _mediaFileService.Get(id); var series = _seriesService.GetSeries(episodeFile.SeriesId); var fullPath = Path.Combine(series.Path, episodeFile.RelativePath); + var subfolder = _diskProvider.GetParentFolder(series.Path).GetRelativePath(_diskProvider.GetParentFolder(fullPath)); _logger.Info("Deleting episode file: {0}", fullPath); - _recycleBinProvider.DeleteFile(fullPath); + _recycleBinProvider.DeleteFile(fullPath, subfolder); _mediaFileService.Delete(episodeFile, DeleteMediaFileReason.Manual); } diff --git a/src/NzbDrone.Core.Test/MediaFiles/UpgradeMediaFileServiceFixture.cs b/src/NzbDrone.Core.Test/MediaFiles/UpgradeMediaFileServiceFixture.cs index 2dfb17e8b..59c97a8d0 100644 --- a/src/NzbDrone.Core.Test/MediaFiles/UpgradeMediaFileServiceFixture.cs +++ b/src/NzbDrone.Core.Test/MediaFiles/UpgradeMediaFileServiceFixture.cs @@ -95,7 +95,7 @@ namespace NzbDrone.Core.Test.MediaFiles Subject.UpgradeEpisodeFile(_episodeFile, _localEpisode); - Mocker.GetMock().Verify(v => v.DeleteFile(It.IsAny()), Times.Once()); + Mocker.GetMock().Verify(v => v.DeleteFile(It.IsAny(), It.IsAny()), Times.Once()); } [Test] @@ -105,7 +105,7 @@ namespace NzbDrone.Core.Test.MediaFiles Subject.UpgradeEpisodeFile(_episodeFile, _localEpisode); - Mocker.GetMock().Verify(v => v.DeleteFile(It.IsAny()), Times.Once()); + Mocker.GetMock().Verify(v => v.DeleteFile(It.IsAny(), It.IsAny()), Times.Once()); } [Test] @@ -115,7 +115,7 @@ namespace NzbDrone.Core.Test.MediaFiles Subject.UpgradeEpisodeFile(_episodeFile, _localEpisode); - Mocker.GetMock().Verify(v => v.DeleteFile(It.IsAny()), Times.Exactly(2)); + Mocker.GetMock().Verify(v => v.DeleteFile(It.IsAny(), It.IsAny()), Times.Exactly(2)); } [Test] @@ -153,7 +153,7 @@ namespace NzbDrone.Core.Test.MediaFiles Subject.UpgradeEpisodeFile(_episodeFile, _localEpisode); - Mocker.GetMock().Verify(v => v.DeleteFile(It.IsAny()), Times.Never()); + Mocker.GetMock().Verify(v => v.DeleteFile(It.IsAny(), It.IsAny()), Times.Never()); } [Test] diff --git a/src/NzbDrone.Core.Test/ProviderTests/RecycleBinProviderTests/DeleteFileFixture.cs b/src/NzbDrone.Core.Test/ProviderTests/RecycleBinProviderTests/DeleteFileFixture.cs index 3adb28208..4f5433a88 100644 --- a/src/NzbDrone.Core.Test/ProviderTests/RecycleBinProviderTests/DeleteFileFixture.cs +++ b/src/NzbDrone.Core.Test/ProviderTests/RecycleBinProviderTests/DeleteFileFixture.cs @@ -75,5 +75,17 @@ namespace NzbDrone.Core.Test.ProviderTests.RecycleBinProviderTests Mocker.GetMock().Verify(v => v.FileSetLastWriteTime(@"C:\Test\Recycle Bin\S01E01.avi".AsOsAgnostic(), It.IsAny()), Times.Once()); } + + [Test] + public void should_use_subfolder_when_passed_in() + { + WithRecycleBin(); + + var path = @"C:\Test\TV\30 Rock\S01E01.avi".AsOsAgnostic(); + + Mocker.Resolve().DeleteFile(path, "30 Rock"); + + Mocker.GetMock().Verify(v => v.TransferFile(path, @"C:\Test\Recycle Bin\30 Rock\S01E01.avi".AsOsAgnostic(), TransferMode.Move, false, true), Times.Once()); + } } } diff --git a/src/NzbDrone.Core/Extras/Files/ExtraFileService.cs b/src/NzbDrone.Core/Extras/Files/ExtraFileService.cs index 54d86e908..ac30f6536 100644 --- a/src/NzbDrone.Core/Extras/Files/ExtraFileService.cs +++ b/src/NzbDrone.Core/Extras/Files/ExtraFileService.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using NLog; using NzbDrone.Common.Disk; +using NzbDrone.Common.Extensions; using NzbDrone.Core.MediaFiles; using NzbDrone.Core.MediaFiles.Events; using NzbDrone.Core.Messaging.Events; @@ -129,7 +130,8 @@ namespace NzbDrone.Core.Extras.Files else { // Send extra files to the recycling bin so they can be recovered if necessary - _recycleBinProvider.DeleteFile(path); + var subfolder = _diskProvider.GetParentFolder(series.Path).GetRelativePath(_diskProvider.GetParentFolder(path)); + _recycleBinProvider.DeleteFile(path, subfolder); } } } diff --git a/src/NzbDrone.Core/MediaFiles/RecycleBinProvider.cs b/src/NzbDrone.Core/MediaFiles/RecycleBinProvider.cs index 520fbf676..540164a7c 100644 --- a/src/NzbDrone.Core/MediaFiles/RecycleBinProvider.cs +++ b/src/NzbDrone.Core/MediaFiles/RecycleBinProvider.cs @@ -15,7 +15,7 @@ namespace NzbDrone.Core.MediaFiles public interface IRecycleBinProvider { void DeleteFolder(string path); - void DeleteFile(string path); + void DeleteFile(string path, string subfolder = ""); void Empty(); void Cleanup(); } @@ -73,7 +73,7 @@ namespace NzbDrone.Core.MediaFiles } } - public void DeleteFile(string path) + public void DeleteFile(string path, string subfolder = "") { _logger.Debug("Attempting to send '{0}' to recycling bin", path); var recyclingBin = _configService.RecycleBin; @@ -94,7 +94,10 @@ namespace NzbDrone.Core.MediaFiles else { var fileInfo = new FileInfo(path); - var destination = Path.Combine(recyclingBin, fileInfo.Name); + var destinationFolder = Path.Combine(recyclingBin, subfolder); + var destination = Path.Combine(destinationFolder, fileInfo.Name); + + _diskProvider.CreateFolder(destinationFolder); var index = 1; while (_diskProvider.FileExists(destination)) @@ -102,11 +105,11 @@ namespace NzbDrone.Core.MediaFiles index++; if (fileInfo.Extension.IsNullOrWhiteSpace()) { - destination = Path.Combine(recyclingBin, fileInfo.Name + "_" + index); + destination = Path.Combine(destinationFolder, fileInfo.Name + "_" + index); } else { - destination = Path.Combine(recyclingBin, Path.GetFileNameWithoutExtension(fileInfo.Name) + "_" + index + fileInfo.Extension); + destination = Path.Combine(destinationFolder, Path.GetFileNameWithoutExtension(fileInfo.Name) + "_" + index + fileInfo.Extension); } } diff --git a/src/NzbDrone.Core/MediaFiles/UpgradeMediaFileService.cs b/src/NzbDrone.Core/MediaFiles/UpgradeMediaFileService.cs index 95f245e3e..d6c270d2c 100644 --- a/src/NzbDrone.Core/MediaFiles/UpgradeMediaFileService.cs +++ b/src/NzbDrone.Core/MediaFiles/UpgradeMediaFileService.cs @@ -2,6 +2,7 @@ using System.Linq; using NLog; using NzbDrone.Common.Disk; +using NzbDrone.Common.Extensions; using NzbDrone.Core.Parser.Model; namespace NzbDrone.Core.MediaFiles @@ -44,11 +45,12 @@ namespace NzbDrone.Core.MediaFiles { var file = existingFile.First(); var episodeFilePath = Path.Combine(localEpisode.Series.Path, file.RelativePath); + var subfolder = _diskProvider.GetParentFolder(localEpisode.Series.Path).GetRelativePath(_diskProvider.GetParentFolder(episodeFilePath)); if (_diskProvider.FileExists(episodeFilePath)) { _logger.Debug("Removing existing episode file: {0}", file); - _recycleBinProvider.DeleteFile(episodeFilePath); + _recycleBinProvider.DeleteFile(episodeFilePath, subfolder); } moveFileResult.OldFiles.Add(file);