New: Episode files sent to Recycling Bin are put into subfolders

Closes #401
pull/6/head
Mark McDowall 8 years ago
parent c20b152c28
commit 83370ddbbb

@ -2,6 +2,8 @@
using System.IO; using System.IO;
using NLog; using NLog;
using NzbDrone.Api.REST; using NzbDrone.Api.REST;
using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Datastore.Events; using NzbDrone.Core.Datastore.Events;
using NzbDrone.Core.MediaFiles; using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.MediaFiles.Events; using NzbDrone.Core.MediaFiles.Events;
@ -16,6 +18,7 @@ namespace NzbDrone.Api.EpisodeFiles
IHandle<EpisodeFileAddedEvent> IHandle<EpisodeFileAddedEvent>
{ {
private readonly IMediaFileService _mediaFileService; private readonly IMediaFileService _mediaFileService;
private readonly IDiskProvider _diskProvider;
private readonly IRecycleBinProvider _recycleBinProvider; private readonly IRecycleBinProvider _recycleBinProvider;
private readonly ISeriesService _seriesService; private readonly ISeriesService _seriesService;
private readonly IQualityUpgradableSpecification _qualityUpgradableSpecification; private readonly IQualityUpgradableSpecification _qualityUpgradableSpecification;
@ -23,6 +26,7 @@ namespace NzbDrone.Api.EpisodeFiles
public EpisodeFileModule(IBroadcastSignalRMessage signalRBroadcaster, public EpisodeFileModule(IBroadcastSignalRMessage signalRBroadcaster,
IMediaFileService mediaFileService, IMediaFileService mediaFileService,
IDiskProvider diskProvider,
IRecycleBinProvider recycleBinProvider, IRecycleBinProvider recycleBinProvider,
ISeriesService seriesService, ISeriesService seriesService,
IQualityUpgradableSpecification qualityUpgradableSpecification, IQualityUpgradableSpecification qualityUpgradableSpecification,
@ -30,6 +34,7 @@ namespace NzbDrone.Api.EpisodeFiles
: base(signalRBroadcaster) : base(signalRBroadcaster)
{ {
_mediaFileService = mediaFileService; _mediaFileService = mediaFileService;
_diskProvider = diskProvider;
_recycleBinProvider = recycleBinProvider; _recycleBinProvider = recycleBinProvider;
_seriesService = seriesService; _seriesService = seriesService;
_qualityUpgradableSpecification = qualityUpgradableSpecification; _qualityUpgradableSpecification = qualityUpgradableSpecification;
@ -74,9 +79,10 @@ namespace NzbDrone.Api.EpisodeFiles
var episodeFile = _mediaFileService.Get(id); var episodeFile = _mediaFileService.Get(id);
var series = _seriesService.GetSeries(episodeFile.SeriesId); var series = _seriesService.GetSeries(episodeFile.SeriesId);
var fullPath = Path.Combine(series.Path, episodeFile.RelativePath); 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); _logger.Info("Deleting episode file: {0}", fullPath);
_recycleBinProvider.DeleteFile(fullPath); _recycleBinProvider.DeleteFile(fullPath, subfolder);
_mediaFileService.Delete(episodeFile, DeleteMediaFileReason.Manual); _mediaFileService.Delete(episodeFile, DeleteMediaFileReason.Manual);
} }

@ -95,7 +95,7 @@ namespace NzbDrone.Core.Test.MediaFiles
Subject.UpgradeEpisodeFile(_episodeFile, _localEpisode); Subject.UpgradeEpisodeFile(_episodeFile, _localEpisode);
Mocker.GetMock<IRecycleBinProvider>().Verify(v => v.DeleteFile(It.IsAny<string>()), Times.Once()); Mocker.GetMock<IRecycleBinProvider>().Verify(v => v.DeleteFile(It.IsAny<string>(), It.IsAny<string>()), Times.Once());
} }
[Test] [Test]
@ -105,7 +105,7 @@ namespace NzbDrone.Core.Test.MediaFiles
Subject.UpgradeEpisodeFile(_episodeFile, _localEpisode); Subject.UpgradeEpisodeFile(_episodeFile, _localEpisode);
Mocker.GetMock<IRecycleBinProvider>().Verify(v => v.DeleteFile(It.IsAny<string>()), Times.Once()); Mocker.GetMock<IRecycleBinProvider>().Verify(v => v.DeleteFile(It.IsAny<string>(), It.IsAny<string>()), Times.Once());
} }
[Test] [Test]
@ -115,7 +115,7 @@ namespace NzbDrone.Core.Test.MediaFiles
Subject.UpgradeEpisodeFile(_episodeFile, _localEpisode); Subject.UpgradeEpisodeFile(_episodeFile, _localEpisode);
Mocker.GetMock<IRecycleBinProvider>().Verify(v => v.DeleteFile(It.IsAny<string>()), Times.Exactly(2)); Mocker.GetMock<IRecycleBinProvider>().Verify(v => v.DeleteFile(It.IsAny<string>(), It.IsAny<string>()), Times.Exactly(2));
} }
[Test] [Test]
@ -153,7 +153,7 @@ namespace NzbDrone.Core.Test.MediaFiles
Subject.UpgradeEpisodeFile(_episodeFile, _localEpisode); Subject.UpgradeEpisodeFile(_episodeFile, _localEpisode);
Mocker.GetMock<IRecycleBinProvider>().Verify(v => v.DeleteFile(It.IsAny<string>()), Times.Never()); Mocker.GetMock<IRecycleBinProvider>().Verify(v => v.DeleteFile(It.IsAny<string>(), It.IsAny<string>()), Times.Never());
} }
[Test] [Test]

@ -75,5 +75,17 @@ namespace NzbDrone.Core.Test.ProviderTests.RecycleBinProviderTests
Mocker.GetMock<IDiskProvider>().Verify(v => v.FileSetLastWriteTime(@"C:\Test\Recycle Bin\S01E01.avi".AsOsAgnostic(), It.IsAny<DateTime>()), Times.Once()); Mocker.GetMock<IDiskProvider>().Verify(v => v.FileSetLastWriteTime(@"C:\Test\Recycle Bin\S01E01.avi".AsOsAgnostic(), It.IsAny<DateTime>()), Times.Once());
} }
[Test]
public void should_use_subfolder_when_passed_in()
{
WithRecycleBin();
var path = @"C:\Test\TV\30 Rock\S01E01.avi".AsOsAgnostic();
Mocker.Resolve<RecycleBinProvider>().DeleteFile(path, "30 Rock");
Mocker.GetMock<IDiskTransferService>().Verify(v => v.TransferFile(path, @"C:\Test\Recycle Bin\30 Rock\S01E01.avi".AsOsAgnostic(), TransferMode.Move, false, true), Times.Once());
}
} }
} }

@ -4,6 +4,7 @@ using System.IO;
using System.Linq; using System.Linq;
using NLog; using NLog;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.MediaFiles; using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.MediaFiles.Events; using NzbDrone.Core.MediaFiles.Events;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
@ -129,7 +130,8 @@ namespace NzbDrone.Core.Extras.Files
else else
{ {
// Send extra files to the recycling bin so they can be recovered if necessary // 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);
} }
} }
} }

@ -15,7 +15,7 @@ namespace NzbDrone.Core.MediaFiles
public interface IRecycleBinProvider public interface IRecycleBinProvider
{ {
void DeleteFolder(string path); void DeleteFolder(string path);
void DeleteFile(string path); void DeleteFile(string path, string subfolder = "");
void Empty(); void Empty();
void Cleanup(); 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); _logger.Debug("Attempting to send '{0}' to recycling bin", path);
var recyclingBin = _configService.RecycleBin; var recyclingBin = _configService.RecycleBin;
@ -94,7 +94,10 @@ namespace NzbDrone.Core.MediaFiles
else else
{ {
var fileInfo = new FileInfo(path); 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; var index = 1;
while (_diskProvider.FileExists(destination)) while (_diskProvider.FileExists(destination))
@ -102,11 +105,11 @@ namespace NzbDrone.Core.MediaFiles
index++; index++;
if (fileInfo.Extension.IsNullOrWhiteSpace()) if (fileInfo.Extension.IsNullOrWhiteSpace())
{ {
destination = Path.Combine(recyclingBin, fileInfo.Name + "_" + index); destination = Path.Combine(destinationFolder, fileInfo.Name + "_" + index);
} }
else else
{ {
destination = Path.Combine(recyclingBin, Path.GetFileNameWithoutExtension(fileInfo.Name) + "_" + index + fileInfo.Extension); destination = Path.Combine(destinationFolder, Path.GetFileNameWithoutExtension(fileInfo.Name) + "_" + index + fileInfo.Extension);
} }
} }

@ -2,6 +2,7 @@
using System.Linq; using System.Linq;
using NLog; using NLog;
using NzbDrone.Common.Disk; using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.MediaFiles namespace NzbDrone.Core.MediaFiles
@ -44,11 +45,12 @@ namespace NzbDrone.Core.MediaFiles
{ {
var file = existingFile.First(); var file = existingFile.First();
var episodeFilePath = Path.Combine(localEpisode.Series.Path, file.RelativePath); var episodeFilePath = Path.Combine(localEpisode.Series.Path, file.RelativePath);
var subfolder = _diskProvider.GetParentFolder(localEpisode.Series.Path).GetRelativePath(_diskProvider.GetParentFolder(episodeFilePath));
if (_diskProvider.FileExists(episodeFilePath)) if (_diskProvider.FileExists(episodeFilePath))
{ {
_logger.Debug("Removing existing episode file: {0}", file); _logger.Debug("Removing existing episode file: {0}", file);
_recycleBinProvider.DeleteFile(episodeFilePath); _recycleBinProvider.DeleteFile(episodeFilePath, subfolder);
} }
moveFileResult.OldFiles.Add(file); moveFileResult.OldFiles.Add(file);

Loading…
Cancel
Save