diff --git a/frontend/src/Settings/MediaManagement/MediaManagement.js b/frontend/src/Settings/MediaManagement/MediaManagement.js
index 11ae6cf24..16a80f031 100644
--- a/frontend/src/Settings/MediaManagement/MediaManagement.js
+++ b/frontend/src/Settings/MediaManagement/MediaManagement.js
@@ -316,11 +316,27 @@ class MediaManagement extends Component {
type={inputTypes.PATH}
name="recycleBin"
helpText="Episode files will go here when deleted instead of being permanently deleted"
- helpTextWarning="Files in the recycle bin older than a week will be cleaned up automatically"
onChange={onInputChange}
{...settings.recycleBin}
/>
+
+
+ Recycling Bin Cleanup
+
+
+
{
diff --git a/src/NzbDrone.Core.Test/ProviderTests/RecycleBinProviderTests/CleanupFixture.cs b/src/NzbDrone.Core.Test/ProviderTests/RecycleBinProviderTests/CleanupFixture.cs
index e38908474..5e336420b 100644
--- a/src/NzbDrone.Core.Test/ProviderTests/RecycleBinProviderTests/CleanupFixture.cs
+++ b/src/NzbDrone.Core.Test/ProviderTests/RecycleBinProviderTests/CleanupFixture.cs
@@ -37,6 +37,7 @@ private void WithNonExpired()
public void Setup()
{
Mocker.GetMock().SetupGet(s => s.RecycleBin).Returns(RecycleBin);
+ Mocker.GetMock().SetupGet(s => s.RecycleBinCleanupDays).Returns(7);
Mocker.GetMock().Setup(s => s.GetDirectories(RecycleBin))
.Returns(new [] { @"C:\Test\RecycleBin\Folder1", @"C:\Test\RecycleBin\Folder2", @"C:\Test\RecycleBin\Folder3" });
@@ -55,6 +56,16 @@ public void should_return_if_recycleBin_not_configured()
Mocker.GetMock().Verify(v => v.GetDirectories(It.IsAny()), Times.Never());
}
+ [Test]
+ public void should_return_if_recycleBinCleanupDays_is_zero()
+ {
+ Mocker.GetMock().SetupGet(s => s.RecycleBinCleanupDays).Returns(0);
+
+ Mocker.Resolve().Cleanup();
+
+ Mocker.GetMock().Verify(v => v.GetDirectories(It.IsAny()), Times.Never());
+ }
+
[Test]
public void should_delete_all_expired_files()
{
diff --git a/src/NzbDrone.Core/Configuration/ConfigService.cs b/src/NzbDrone.Core/Configuration/ConfigService.cs
index bf6c1ed1d..822ff1b7a 100644
--- a/src/NzbDrone.Core/Configuration/ConfigService.cs
+++ b/src/NzbDrone.Core/Configuration/ConfigService.cs
@@ -94,6 +94,12 @@ public string RecycleBin
set { SetValue("RecycleBin", value); }
}
+ public int RecycleBinCleanupDays
+ {
+ get { return GetValueInt("RecycleBinCleanupDays", 7); }
+ set { SetValue("RecycleBinCleanupDays", value); }
+ }
+
public int RssSyncInterval
{
get { return GetValueInt("RssSyncInterval", 15); }
diff --git a/src/NzbDrone.Core/Configuration/IConfigService.cs b/src/NzbDrone.Core/Configuration/IConfigService.cs
index a16b64f76..5374f61be 100644
--- a/src/NzbDrone.Core/Configuration/IConfigService.cs
+++ b/src/NzbDrone.Core/Configuration/IConfigService.cs
@@ -27,6 +27,7 @@ public interface IConfigService
//Media Management
bool AutoUnmonitorPreviouslyDownloadedEpisodes { get; set; }
string RecycleBin { get; set; }
+ int RecycleBinCleanupDays { get; set; }
ProperDownloadTypes DownloadPropersAndRepacks { get; set; }
bool CreateEmptySeriesFolders { get; set; }
bool DeleteEmptyFolders { get; set; }
@@ -39,7 +40,6 @@ public interface IConfigService
RescanAfterRefreshType RescanAfterRefresh { get; set; }
EpisodeTitleRequiredType EpisodeTitleRequired { get; set; }
-
//Permissions (Media Management)
bool SetPermissionsLinux { get; set; }
string FileChmod { get; set; }
diff --git a/src/NzbDrone.Core/MediaFiles/RecycleBinProvider.cs b/src/NzbDrone.Core/MediaFiles/RecycleBinProvider.cs
index 85c628ad1..686e5375e 100644
--- a/src/NzbDrone.Core/MediaFiles/RecycleBinProvider.cs
+++ b/src/NzbDrone.Core/MediaFiles/RecycleBinProvider.cs
@@ -157,11 +157,19 @@ public void Cleanup()
return;
}
- _logger.Info("Removing items older than 7 days from the recycling bin");
+ var cleanupDays = _configService.RecycleBinCleanupDays;
+
+ if (cleanupDays == 0)
+ {
+ _logger.Info("Automatic cleanup of Recycle Bin is disabled");
+ return;
+ }
+
+ _logger.Info("Removing items older than {0} days from the recycling bin", cleanupDays);
foreach (var file in _diskProvider.GetFiles(_configService.RecycleBin, SearchOption.AllDirectories))
{
- if (_diskProvider.FileGetLastWrite(file).AddDays(7) > DateTime.UtcNow)
+ if (_diskProvider.FileGetLastWrite(file).AddDays(cleanupDays) > DateTime.UtcNow)
{
_logger.Debug("File hasn't expired yet, skipping: {0}", file);
continue;
diff --git a/src/Sonarr.Api.V3/Config/MediaManagementConfigModule.cs b/src/Sonarr.Api.V3/Config/MediaManagementConfigModule.cs
index 6d241de86..85dd39c7b 100644
--- a/src/Sonarr.Api.V3/Config/MediaManagementConfigModule.cs
+++ b/src/Sonarr.Api.V3/Config/MediaManagementConfigModule.cs
@@ -9,6 +9,7 @@ public class MediaManagementConfigModule : SonarrConfigModule c.RecycleBinCleanupDays).GreaterThanOrEqualTo(0);
SharedValidator.RuleFor(c => c.FileChmod).NotEmpty();
SharedValidator.RuleFor(c => c.FolderChmod).NotEmpty();
SharedValidator.RuleFor(c => c.RecycleBin).IsValidPath().SetValidator(pathExistsValidator).When(c => !string.IsNullOrWhiteSpace(c.RecycleBin));
diff --git a/src/Sonarr.Api.V3/Config/MediaManagementConfigResource.cs b/src/Sonarr.Api.V3/Config/MediaManagementConfigResource.cs
index 338c9e282..c76d0fa24 100644
--- a/src/Sonarr.Api.V3/Config/MediaManagementConfigResource.cs
+++ b/src/Sonarr.Api.V3/Config/MediaManagementConfigResource.cs
@@ -10,6 +10,7 @@ public class MediaManagementConfigResource : RestResource
{
public bool AutoUnmonitorPreviouslyDownloadedEpisodes { get; set; }
public string RecycleBin { get; set; }
+ public int RecycleBinCleanupDays { get; set; }
public ProperDownloadTypes DownloadPropersAndRepacks { get; set; }
public bool CreateEmptySeriesFolders { get; set; }
public bool DeleteEmptyFolders { get; set; }
@@ -38,6 +39,7 @@ public static MediaManagementConfigResource ToResource(IConfigService model)
{
AutoUnmonitorPreviouslyDownloadedEpisodes = model.AutoUnmonitorPreviouslyDownloadedEpisodes,
RecycleBin = model.RecycleBin,
+ RecycleBinCleanupDays = model.RecycleBinCleanupDays,
DownloadPropersAndRepacks = model.DownloadPropersAndRepacks,
CreateEmptySeriesFolders = model.CreateEmptySeriesFolders,
DeleteEmptyFolders = model.DeleteEmptyFolders,