mirror of
https://github.com/Sonarr/Sonarr.git
synced 2024-12-16 11:37:58 +02:00
Merge branch 'blackhole-delay' into develop
This commit is contained in:
commit
19b8fb6d8b
@ -10,12 +10,16 @@ public static class HashConverter
|
|||||||
|
|
||||||
public static int GetHashInt31(string target)
|
public static int GetHashInt31(string target)
|
||||||
{
|
{
|
||||||
byte[] hash;
|
var hash = GetHash(target);
|
||||||
|
return BitConverter.ToInt32(hash, 0) & 0x7fffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] GetHash(string target)
|
||||||
|
{
|
||||||
lock (Sha1)
|
lock (Sha1)
|
||||||
{
|
{
|
||||||
hash = Sha1.ComputeHash(Encoding.Default.GetBytes(target));
|
return Sha1.ComputeHash(Encoding.Default.GetBytes(target));
|
||||||
}
|
}
|
||||||
return BitConverter.ToInt32(hash, 0) & 0x7fffffff;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,5 +100,10 @@ public static byte[] HexToByteArray(this string input)
|
|||||||
.Select(x => Convert.ToByte(input.Substring(x, 2), 16))
|
.Select(x => Convert.ToByte(input.Substring(x, 2), 16))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string ToHexString(this byte[] input)
|
||||||
|
{
|
||||||
|
return string.Concat(Array.ConvertAll(input, x => x.ToString("X2")));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,94 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using FluentAssertions;
|
||||||
|
using Moq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Common.Disk;
|
||||||
|
using NzbDrone.Core.Download;
|
||||||
|
using NzbDrone.Test.Common;
|
||||||
|
using System.Threading;
|
||||||
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
using NzbDrone.Core.Download.Clients.Blackhole;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class ScanWatchFolderFixture : CoreTest<ScanWatchFolder>
|
||||||
|
{
|
||||||
|
protected readonly string _title = "Droned.S01E01.Pilot.1080p.WEB-DL-DRONE";
|
||||||
|
protected string _completedDownloadFolder = @"c:\blackhole\completed".AsOsAgnostic();
|
||||||
|
|
||||||
|
protected void GivenCompletedItem()
|
||||||
|
{
|
||||||
|
var targetDir = Path.Combine(_completedDownloadFolder, _title);
|
||||||
|
Mocker.GetMock<IDiskProvider>()
|
||||||
|
.Setup(c => c.GetDirectories(_completedDownloadFolder))
|
||||||
|
.Returns(new[] { targetDir });
|
||||||
|
|
||||||
|
Mocker.GetMock<IDiskProvider>()
|
||||||
|
.Setup(c => c.GetFiles(targetDir, SearchOption.AllDirectories))
|
||||||
|
.Returns(new[] { Path.Combine(targetDir, "somefile.mkv") });
|
||||||
|
|
||||||
|
Mocker.GetMock<IDiskProvider>()
|
||||||
|
.Setup(c => c.GetFileSize(It.IsAny<string>()))
|
||||||
|
.Returns(1000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void GivenChangedItem()
|
||||||
|
{
|
||||||
|
var currentSize = Mocker.GetMock<IDiskProvider>().Object.GetFileSize("abc");
|
||||||
|
|
||||||
|
Mocker.GetMock<IDiskProvider>()
|
||||||
|
.Setup(c => c.GetFileSize(It.IsAny<string>()))
|
||||||
|
.Returns(currentSize + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void VerifySingleItem(DownloadItemStatus status)
|
||||||
|
{
|
||||||
|
var items = Subject.GetItems(_completedDownloadFolder, TimeSpan.FromMilliseconds(50)).ToList();
|
||||||
|
|
||||||
|
items.Count.Should().Be(1);
|
||||||
|
items.First().Status.Should().Be(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void GetItems_should_considered_locked_files_queued()
|
||||||
|
{
|
||||||
|
GivenCompletedItem();
|
||||||
|
|
||||||
|
Mocker.GetMock<IDiskProvider>()
|
||||||
|
.Setup(c => c.IsFileLocked(It.IsAny<string>()))
|
||||||
|
.Returns(true);
|
||||||
|
|
||||||
|
Thread.Sleep(60);
|
||||||
|
|
||||||
|
VerifySingleItem(DownloadItemStatus.Downloading);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void GetItems_should_considered_changing_files_queued()
|
||||||
|
{
|
||||||
|
GivenCompletedItem();
|
||||||
|
|
||||||
|
VerifySingleItem(DownloadItemStatus.Downloading);
|
||||||
|
|
||||||
|
// If we keep changing the file every 20ms we should stay Downloading.
|
||||||
|
for (int i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
TestLogger.Info("Iteration {0}", i);
|
||||||
|
|
||||||
|
GivenChangedItem();
|
||||||
|
|
||||||
|
VerifySingleItem(DownloadItemStatus.Downloading);
|
||||||
|
|
||||||
|
Thread.Sleep(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Until it remains unchanged for >=50ms.
|
||||||
|
Thread.Sleep(60);
|
||||||
|
|
||||||
|
VerifySingleItem(DownloadItemStatus.Completed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -8,7 +8,7 @@
|
|||||||
using NzbDrone.Common.Disk;
|
using NzbDrone.Common.Disk;
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Core.Download;
|
using NzbDrone.Core.Download;
|
||||||
using NzbDrone.Core.Download.Clients.TorrentBlackhole;
|
using NzbDrone.Core.Download.Clients.Blackhole;
|
||||||
using NzbDrone.Core.Exceptions;
|
using NzbDrone.Core.Exceptions;
|
||||||
using NzbDrone.Core.MediaFiles.TorrentInfo;
|
using NzbDrone.Core.MediaFiles.TorrentInfo;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
@ -30,6 +30,8 @@ public void Setup()
|
|||||||
_blackholeFolder = @"c:\blackhole\torrent".AsOsAgnostic();
|
_blackholeFolder = @"c:\blackhole\torrent".AsOsAgnostic();
|
||||||
_filePath = (@"c:\blackhole\torrent\" + _title + ".torrent").AsOsAgnostic();
|
_filePath = (@"c:\blackhole\torrent\" + _title + ".torrent").AsOsAgnostic();
|
||||||
|
|
||||||
|
Mocker.SetConstant<IScanWatchFolder>(Mocker.Resolve<ScanWatchFolder>());
|
||||||
|
|
||||||
Subject.Definition = new DownloadClientDefinition();
|
Subject.Definition = new DownloadClientDefinition();
|
||||||
Subject.Definition.Settings = new TorrentBlackholeSettings
|
Subject.Definition.Settings = new TorrentBlackholeSettings
|
||||||
{
|
{
|
||||||
@ -56,13 +58,14 @@ protected void GivenFailedDownload()
|
|||||||
protected void GivenCompletedItem()
|
protected void GivenCompletedItem()
|
||||||
{
|
{
|
||||||
var targetDir = Path.Combine(_completedDownloadFolder, _title);
|
var targetDir = Path.Combine(_completedDownloadFolder, _title);
|
||||||
|
|
||||||
Mocker.GetMock<IDiskProvider>()
|
Mocker.GetMock<IDiskProvider>()
|
||||||
.Setup(c => c.GetDirectories(_completedDownloadFolder))
|
.Setup(c => c.GetDirectories(_completedDownloadFolder))
|
||||||
.Returns(new[] { targetDir });
|
.Returns(new[] { targetDir });
|
||||||
|
|
||||||
Mocker.GetMock<IDiskProvider>()
|
Mocker.GetMock<IDiskProvider>()
|
||||||
.Setup(c => c.GetFiles(targetDir, SearchOption.AllDirectories))
|
.Setup(c => c.GetFiles(targetDir, SearchOption.AllDirectories))
|
||||||
.Returns(new[] { Path.Combine(_completedDownloadFolder, "somefile.mkv") });
|
.Returns(new[] { Path.Combine(targetDir, "somefile.mkv") });
|
||||||
|
|
||||||
Mocker.GetMock<IDiskProvider>()
|
Mocker.GetMock<IDiskProvider>()
|
||||||
.Setup(c => c.GetFileSize(It.IsAny<string>()))
|
.Setup(c => c.GetFileSize(It.IsAny<string>()))
|
||||||
@ -87,6 +90,8 @@ protected override RemoteEpisode CreateRemoteEpisode()
|
|||||||
[Test]
|
[Test]
|
||||||
public void completed_download_should_have_required_properties()
|
public void completed_download_should_have_required_properties()
|
||||||
{
|
{
|
||||||
|
Subject.ScanGracePeriod = TimeSpan.Zero;
|
||||||
|
|
||||||
GivenCompletedItem();
|
GivenCompletedItem();
|
||||||
|
|
||||||
var result = Subject.GetItems().Single();
|
var result = Subject.GetItems().Single();
|
||||||
@ -94,6 +99,16 @@ public void completed_download_should_have_required_properties()
|
|||||||
VerifyCompleted(result);
|
VerifyCompleted(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void partial_download_should_have_required_properties()
|
||||||
|
{
|
||||||
|
GivenCompletedItem();
|
||||||
|
|
||||||
|
var result = Subject.GetItems().Single();
|
||||||
|
|
||||||
|
VerifyPostprocessing(result);
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_return_category()
|
public void should_return_category()
|
||||||
{
|
{
|
||||||
@ -142,21 +157,6 @@ public void Download_should_throw_if_magnet_and_torrent_url_does_not_exist()
|
|||||||
Assert.Throws<ReleaseDownloadException>(() => Subject.Download(remoteEpisode));
|
Assert.Throws<ReleaseDownloadException>(() => Subject.Download(remoteEpisode));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void GetItems_should_considered_locked_files_queued()
|
|
||||||
{
|
|
||||||
GivenCompletedItem();
|
|
||||||
|
|
||||||
Mocker.GetMock<IDiskProvider>()
|
|
||||||
.Setup(c => c.IsFileLocked(It.IsAny<string>()))
|
|
||||||
.Returns(true);
|
|
||||||
|
|
||||||
var items = Subject.GetItems().ToList();
|
|
||||||
|
|
||||||
items.Count.Should().Be(1);
|
|
||||||
items.First().Status.Should().Be(DownloadItemStatus.Downloading);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void RemoveItem_should_delete_file()
|
public void RemoveItem_should_delete_file()
|
||||||
{
|
{
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
using NzbDrone.Common.Disk;
|
using NzbDrone.Common.Disk;
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Core.Download;
|
using NzbDrone.Core.Download;
|
||||||
using NzbDrone.Core.Download.Clients.UsenetBlackhole;
|
using NzbDrone.Core.Download.Clients.Blackhole;
|
||||||
using NzbDrone.Test.Common;
|
using NzbDrone.Test.Common;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole
|
namespace NzbDrone.Core.Test.Download.DownloadClientTests.Blackhole
|
||||||
@ -29,6 +29,8 @@ public void Setup()
|
|||||||
_blackholeFolder = @"c:\blackhole\nzb".AsOsAgnostic();
|
_blackholeFolder = @"c:\blackhole\nzb".AsOsAgnostic();
|
||||||
_filePath = (@"c:\blackhole\nzb\" + _title + ".nzb").AsOsAgnostic();
|
_filePath = (@"c:\blackhole\nzb\" + _title + ".nzb").AsOsAgnostic();
|
||||||
|
|
||||||
|
Mocker.SetConstant<IScanWatchFolder>(Mocker.Resolve<ScanWatchFolder>());
|
||||||
|
|
||||||
Subject.Definition = new DownloadClientDefinition();
|
Subject.Definition = new DownloadClientDefinition();
|
||||||
Subject.Definition.Settings = new UsenetBlackholeSettings
|
Subject.Definition.Settings = new UsenetBlackholeSettings
|
||||||
{
|
{
|
||||||
@ -58,7 +60,7 @@ protected void GivenCompletedItem()
|
|||||||
|
|
||||||
Mocker.GetMock<IDiskProvider>()
|
Mocker.GetMock<IDiskProvider>()
|
||||||
.Setup(c => c.GetFiles(targetDir, SearchOption.AllDirectories))
|
.Setup(c => c.GetFiles(targetDir, SearchOption.AllDirectories))
|
||||||
.Returns(new[] { Path.Combine(_completedDownloadFolder, "somefile.mkv") });
|
.Returns(new[] { Path.Combine(targetDir, "somefile.mkv") });
|
||||||
|
|
||||||
Mocker.GetMock<IDiskProvider>()
|
Mocker.GetMock<IDiskProvider>()
|
||||||
.Setup(c => c.GetFileSize(It.IsAny<string>()))
|
.Setup(c => c.GetFileSize(It.IsAny<string>()))
|
||||||
@ -68,6 +70,8 @@ protected void GivenCompletedItem()
|
|||||||
[Test]
|
[Test]
|
||||||
public void completed_download_should_have_required_properties()
|
public void completed_download_should_have_required_properties()
|
||||||
{
|
{
|
||||||
|
Subject.ScanGracePeriod = TimeSpan.Zero;
|
||||||
|
|
||||||
GivenCompletedItem();
|
GivenCompletedItem();
|
||||||
|
|
||||||
var result = Subject.GetItems().Single();
|
var result = Subject.GetItems().Single();
|
||||||
@ -75,6 +79,17 @@ public void completed_download_should_have_required_properties()
|
|||||||
VerifyCompleted(result);
|
VerifyCompleted(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void partial_download_should_have_required_properties()
|
||||||
|
{
|
||||||
|
GivenCompletedItem();
|
||||||
|
|
||||||
|
var result = Subject.GetItems().Single();
|
||||||
|
|
||||||
|
VerifyPostprocessing(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_return_category()
|
public void should_return_category()
|
||||||
{
|
{
|
||||||
@ -114,20 +129,6 @@ public void Download_should_replace_illegal_characters_in_title()
|
|||||||
Mocker.GetMock<IHttpClient>().Verify(c => c.DownloadFile(It.IsAny<string>(), It.IsAny<string>()), Times.Never());
|
Mocker.GetMock<IHttpClient>().Verify(c => c.DownloadFile(It.IsAny<string>(), It.IsAny<string>()), Times.Never());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void GetItems_should_considered_locked_files_downloading()
|
|
||||||
{
|
|
||||||
GivenCompletedItem();
|
|
||||||
|
|
||||||
Mocker.GetMock<IDiskProvider>()
|
|
||||||
.Setup(c => c.IsFileLocked(It.IsAny<string>()))
|
|
||||||
.Returns(true);
|
|
||||||
|
|
||||||
var result = Subject.GetItems().Single();
|
|
||||||
|
|
||||||
result.Status.Should().Be(DownloadItemStatus.Downloading);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void RemoveItem_should_delete_file()
|
public void RemoveItem_should_delete_file()
|
||||||
{
|
{
|
||||||
|
@ -96,6 +96,15 @@ protected void VerifyDownloading(DownloadClientItem downloadClientItem)
|
|||||||
downloadClientItem.Status.Should().Be(DownloadItemStatus.Downloading);
|
downloadClientItem.Status.Should().Be(DownloadItemStatus.Downloading);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void VerifyPostprocessing(DownloadClientItem downloadClientItem)
|
||||||
|
{
|
||||||
|
VerifyIdentifiable(downloadClientItem);
|
||||||
|
|
||||||
|
//downloadClientItem.RemainingTime.Should().NotBe(TimeSpan.Zero);
|
||||||
|
//downloadClientItem.OutputPath.Should().NotBeNullOrEmpty();
|
||||||
|
downloadClientItem.Status.Should().Be(DownloadItemStatus.Downloading);
|
||||||
|
}
|
||||||
|
|
||||||
protected void VerifyCompleted(DownloadClientItem downloadClientItem)
|
protected void VerifyCompleted(DownloadClientItem downloadClientItem)
|
||||||
{
|
{
|
||||||
VerifyIdentifiable(downloadClientItem);
|
VerifyIdentifiable(downloadClientItem);
|
||||||
|
@ -23,8 +23,6 @@ public class TorrentRssIndexerFixture : CoreTest<TestTorrentRssIndexer>
|
|||||||
[SetUp]
|
[SetUp]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
Mocker.SetConstant<IHttpClient>(Mocker.GetMock<IHttpClient>().Object);
|
|
||||||
Mocker.SetConstant<ICacheManager>(Mocker.Resolve<CacheManager>());
|
|
||||||
Mocker.SetConstant<ITorrentRssSettingsDetector>(Mocker.Resolve<TorrentRssSettingsDetector>());
|
Mocker.SetConstant<ITorrentRssSettingsDetector>(Mocker.Resolve<TorrentRssSettingsDetector>());
|
||||||
Mocker.SetConstant<ITorrentRssParserFactory>(Mocker.Resolve<TorrentRssParserFactory>());
|
Mocker.SetConstant<ITorrentRssParserFactory>(Mocker.Resolve<TorrentRssParserFactory>());
|
||||||
|
|
||||||
|
@ -158,6 +158,7 @@
|
|||||||
<Compile Include="DecisionEngineTests\UpgradeDiskSpecificationFixture.cs" />
|
<Compile Include="DecisionEngineTests\UpgradeDiskSpecificationFixture.cs" />
|
||||||
<Compile Include="Download\CompletedDownloadServiceFixture.cs" />
|
<Compile Include="Download\CompletedDownloadServiceFixture.cs" />
|
||||||
<Compile Include="Download\DownloadApprovedReportsTests\DownloadApprovedFixture.cs" />
|
<Compile Include="Download\DownloadApprovedReportsTests\DownloadApprovedFixture.cs" />
|
||||||
|
<Compile Include="Download\DownloadClientTests\Blackhole\ScanWatchFolderFixture.cs" />
|
||||||
<Compile Include="Download\DownloadClientTests\Blackhole\TorrentBlackholeFixture.cs" />
|
<Compile Include="Download\DownloadClientTests\Blackhole\TorrentBlackholeFixture.cs" />
|
||||||
<Compile Include="Download\DownloadClientTests\Blackhole\UsenetBlackholeFixture.cs" />
|
<Compile Include="Download\DownloadClientTests\Blackhole\UsenetBlackholeFixture.cs" />
|
||||||
<Compile Include="Download\DownloadClientTests\DelugeTests\DelugeFixture.cs" />
|
<Compile Include="Download\DownloadClientTests\DelugeTests\DelugeFixture.cs" />
|
||||||
|
196
src/NzbDrone.Core/Download/Clients/Blackhole/ScanWatchFolder.cs
Normal file
196
src/NzbDrone.Core/Download/Clients/Blackhole/ScanWatchFolder.cs
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
using NLog;
|
||||||
|
using NzbDrone.Common.Cache;
|
||||||
|
using NzbDrone.Common.Crypto;
|
||||||
|
using NzbDrone.Common.Disk;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Core.MediaFiles;
|
||||||
|
using NzbDrone.Core.Organizer;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Download.Clients.Blackhole
|
||||||
|
{
|
||||||
|
public interface IScanWatchFolder
|
||||||
|
{
|
||||||
|
IEnumerable<WatchFolderItem> GetItems(string watchFolder, TimeSpan waitPeriod);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ScanWatchFolder : IScanWatchFolder
|
||||||
|
{
|
||||||
|
private readonly Logger _logger;
|
||||||
|
private readonly IDiskProvider _diskProvider;
|
||||||
|
private readonly IDiskScanService _diskScanService;
|
||||||
|
private readonly ICached<Dictionary<string, WatchFolderItem>> _watchFolderItemCache;
|
||||||
|
|
||||||
|
public ScanWatchFolder(ICacheManager cacheManager, IDiskScanService diskScanService, IDiskProvider diskProvider, Logger logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_diskProvider = diskProvider;
|
||||||
|
_diskScanService = diskScanService;
|
||||||
|
_watchFolderItemCache = cacheManager.GetCache<Dictionary<string, WatchFolderItem>>(GetType());
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<WatchFolderItem> GetItems(string watchFolder, TimeSpan waitPeriod)
|
||||||
|
{
|
||||||
|
var newWatchItems = new Dictionary<string, WatchFolderItem>();
|
||||||
|
var lastWatchItems = _watchFolderItemCache.Get(watchFolder, () => newWatchItems);
|
||||||
|
|
||||||
|
foreach (var newWatchItem in GetDownloadItems(watchFolder, lastWatchItems, waitPeriod))
|
||||||
|
{
|
||||||
|
newWatchItems[newWatchItem.DownloadId] = newWatchItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
_watchFolderItemCache.Set(watchFolder, newWatchItems, TimeSpan.FromMinutes(5));
|
||||||
|
|
||||||
|
return newWatchItems.Values;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<WatchFolderItem> GetDownloadItems(string watchFolder, Dictionary<string, WatchFolderItem> lastWatchItems, TimeSpan waitPeriod)
|
||||||
|
{
|
||||||
|
foreach (var folder in _diskProvider.GetDirectories(watchFolder))
|
||||||
|
{
|
||||||
|
var title = FileNameBuilder.CleanFileName(Path.GetFileName(folder));
|
||||||
|
|
||||||
|
var newWatchItem = new WatchFolderItem
|
||||||
|
{
|
||||||
|
DownloadId = Path.GetFileName(folder) + "_" + _diskProvider.FolderGetCreationTime(folder).Ticks,
|
||||||
|
Title = title,
|
||||||
|
|
||||||
|
OutputPath = new OsPath(folder),
|
||||||
|
|
||||||
|
Status = DownloadItemStatus.Completed,
|
||||||
|
RemainingTime = TimeSpan.Zero
|
||||||
|
};
|
||||||
|
|
||||||
|
var oldWatchItem = lastWatchItems.GetValueOrDefault(newWatchItem.DownloadId);
|
||||||
|
|
||||||
|
if (PreCheckWatchItemExpiry(newWatchItem, oldWatchItem))
|
||||||
|
{
|
||||||
|
var files = _diskProvider.GetFiles(folder, SearchOption.AllDirectories);
|
||||||
|
|
||||||
|
newWatchItem.TotalSize = files.Select(_diskProvider.GetFileSize).Sum();
|
||||||
|
newWatchItem.Hash = GetHash(folder, files);
|
||||||
|
|
||||||
|
if (files.Any(_diskProvider.IsFileLocked))
|
||||||
|
{
|
||||||
|
newWatchItem.Status = DownloadItemStatus.Downloading;
|
||||||
|
newWatchItem.RemainingTime = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateWatchItemExpiry(newWatchItem, oldWatchItem, waitPeriod);
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return newWatchItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var videoFile in _diskScanService.GetVideoFiles(watchFolder, false))
|
||||||
|
{
|
||||||
|
var title = FileNameBuilder.CleanFileName(Path.GetFileName(videoFile));
|
||||||
|
|
||||||
|
var newWatchItem = new WatchFolderItem
|
||||||
|
{
|
||||||
|
DownloadId = Path.GetFileName(videoFile) + "_" + _diskProvider.FileGetLastWrite(videoFile).Ticks,
|
||||||
|
Title = title,
|
||||||
|
|
||||||
|
OutputPath = new OsPath(videoFile),
|
||||||
|
|
||||||
|
Status = DownloadItemStatus.Completed,
|
||||||
|
RemainingTime = TimeSpan.Zero
|
||||||
|
};
|
||||||
|
|
||||||
|
var oldWatchItem = lastWatchItems.GetValueOrDefault(newWatchItem.DownloadId);
|
||||||
|
|
||||||
|
if (PreCheckWatchItemExpiry(oldWatchItem, newWatchItem))
|
||||||
|
{
|
||||||
|
newWatchItem.TotalSize = _diskProvider.GetFileSize(videoFile);
|
||||||
|
newWatchItem.Hash = GetHash(videoFile);
|
||||||
|
|
||||||
|
if (_diskProvider.IsFileLocked(videoFile))
|
||||||
|
{
|
||||||
|
newWatchItem.Status = DownloadItemStatus.Downloading;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateWatchItemExpiry(newWatchItem, oldWatchItem, waitPeriod);
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return newWatchItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool PreCheckWatchItemExpiry(WatchFolderItem newWatchItem, WatchFolderItem oldWatchItem)
|
||||||
|
{
|
||||||
|
if (oldWatchItem == null || oldWatchItem.LastChanged.AddHours(1) > DateTime.UtcNow)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
newWatchItem.TotalSize = oldWatchItem.TotalSize;
|
||||||
|
newWatchItem.Hash = oldWatchItem.Hash;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void UpdateWatchItemExpiry(WatchFolderItem newWatchItem, WatchFolderItem oldWatchItem, TimeSpan waitPeriod)
|
||||||
|
{
|
||||||
|
if (oldWatchItem != null && newWatchItem.Hash == oldWatchItem.Hash)
|
||||||
|
{
|
||||||
|
newWatchItem.LastChanged = oldWatchItem.LastChanged;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newWatchItem.LastChanged = DateTime.UtcNow;
|
||||||
|
}
|
||||||
|
|
||||||
|
var remainingTime = waitPeriod - (DateTime.UtcNow - newWatchItem.LastChanged);
|
||||||
|
|
||||||
|
if (remainingTime > TimeSpan.Zero)
|
||||||
|
{
|
||||||
|
newWatchItem.RemainingTime = remainingTime;
|
||||||
|
newWatchItem.Status = DownloadItemStatus.Downloading;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetHash(string folder, string[] files)
|
||||||
|
{
|
||||||
|
var data = new StringBuilder();
|
||||||
|
|
||||||
|
data.Append(folder);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
data.Append(_diskProvider.FolderGetLastWrite(folder).ToBinary());
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.TraceException(string.Format("Ignored hashing error during scan for {0}", folder), ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var file in files.OrderBy(v => v))
|
||||||
|
{
|
||||||
|
data.Append(GetHash(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
return HashConverter.GetHash(data.ToString()).ToHexString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetHash(string file)
|
||||||
|
{
|
||||||
|
var data = new StringBuilder();
|
||||||
|
|
||||||
|
data.Append(file);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
data.Append(_diskProvider.FileGetLastWrite(file).ToBinary());
|
||||||
|
data.Append(_diskProvider.GetFileSize(file));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.TraceException(string.Format("Ignored hashing error during scan for {0}", file), ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return HashConverter.GetHash(data.ToString()).ToHexString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -15,13 +15,15 @@
|
|||||||
using NzbDrone.Core.RemotePathMappings;
|
using NzbDrone.Core.RemotePathMappings;
|
||||||
using NzbDrone.Core.ThingiProvider;
|
using NzbDrone.Core.ThingiProvider;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Download.Clients.TorrentBlackhole
|
namespace NzbDrone.Core.Download.Clients.Blackhole
|
||||||
{
|
{
|
||||||
public class TorrentBlackhole : TorrentClientBase<TorrentBlackholeSettings>
|
public class TorrentBlackhole : TorrentClientBase<TorrentBlackholeSettings>
|
||||||
{
|
{
|
||||||
private readonly IDiskScanService _diskScanService;
|
private readonly IScanWatchFolder _scanWatchFolder;
|
||||||
|
|
||||||
public TorrentBlackhole(IDiskScanService diskScanService,
|
public TimeSpan ScanGracePeriod { get; set; }
|
||||||
|
|
||||||
|
public TorrentBlackhole(IScanWatchFolder scanWatchFolder,
|
||||||
ITorrentFileInfoReader torrentFileInfoReader,
|
ITorrentFileInfoReader torrentFileInfoReader,
|
||||||
IHttpClient httpClient,
|
IHttpClient httpClient,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
@ -30,7 +32,9 @@ public TorrentBlackhole(IDiskScanService diskScanService,
|
|||||||
Logger logger)
|
Logger logger)
|
||||||
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger)
|
: base(torrentFileInfoReader, httpClient, configService, diskProvider, remotePathMappingService, logger)
|
||||||
{
|
{
|
||||||
_diskScanService = diskScanService;
|
_scanWatchFolder = scanWatchFolder;
|
||||||
|
|
||||||
|
ScanGracePeriod = TimeSpan.FromSeconds(30);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override string AddFromMagnetLink(RemoteEpisode remoteEpisode, string hash, string magnetLink)
|
protected override string AddFromMagnetLink(RemoteEpisode remoteEpisode, string hash, string magnetLink)
|
||||||
@ -72,71 +76,28 @@ public override ProviderMessage Message
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public override IEnumerable<DownloadClientItem> GetItems()
|
public override IEnumerable<DownloadClientItem> GetItems()
|
||||||
{
|
{
|
||||||
foreach (var folder in _diskProvider.GetDirectories(Settings.WatchFolder))
|
foreach (var item in _scanWatchFolder.GetItems(Settings.WatchFolder, ScanGracePeriod))
|
||||||
{
|
{
|
||||||
var title = FileNameBuilder.CleanFileName(Path.GetFileName(folder));
|
yield return new DownloadClientItem
|
||||||
|
|
||||||
var files = _diskProvider.GetFiles(folder, SearchOption.AllDirectories);
|
|
||||||
|
|
||||||
var historyItem = new DownloadClientItem
|
|
||||||
{
|
{
|
||||||
DownloadClient = Definition.Name,
|
DownloadClient = Definition.Name,
|
||||||
DownloadId = Definition.Name + "_" + Path.GetFileName(folder) + "_" + _diskProvider.FolderGetCreationTime(folder).Ticks,
|
DownloadId = Definition.Name + "_" + item.DownloadId,
|
||||||
Category = "sonarr",
|
Category = "sonarr",
|
||||||
Title = title,
|
Title = item.Title,
|
||||||
|
|
||||||
TotalSize = files.Select(_diskProvider.GetFileSize).Sum(),
|
TotalSize = item.TotalSize,
|
||||||
|
RemainingTime = item.RemainingTime,
|
||||||
|
|
||||||
OutputPath = new OsPath(folder)
|
OutputPath = item.OutputPath,
|
||||||
|
|
||||||
|
Status = item.Status,
|
||||||
|
|
||||||
|
IsReadOnly = Settings.ReadOnly
|
||||||
};
|
};
|
||||||
|
|
||||||
if (files.Any(_diskProvider.IsFileLocked))
|
|
||||||
{
|
|
||||||
historyItem.Status = DownloadItemStatus.Downloading;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
historyItem.Status = DownloadItemStatus.Completed;
|
|
||||||
|
|
||||||
historyItem.RemainingTime = TimeSpan.Zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
historyItem.IsReadOnly = Settings.ReadOnly;
|
|
||||||
|
|
||||||
yield return historyItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var videoFile in _diskScanService.GetVideoFiles(Settings.WatchFolder, false))
|
|
||||||
{
|
|
||||||
var title = FileNameBuilder.CleanFileName(Path.GetFileName(videoFile));
|
|
||||||
|
|
||||||
var historyItem = new DownloadClientItem
|
|
||||||
{
|
|
||||||
DownloadClient = Definition.Name,
|
|
||||||
DownloadId = Definition.Name + "_" + Path.GetFileName(videoFile) + "_" + _diskProvider.FileGetLastWrite(videoFile).Ticks,
|
|
||||||
Category = "sonarr",
|
|
||||||
Title = title,
|
|
||||||
|
|
||||||
TotalSize = _diskProvider.GetFileSize(videoFile),
|
|
||||||
|
|
||||||
OutputPath = new OsPath(videoFile)
|
|
||||||
};
|
|
||||||
|
|
||||||
if (_diskProvider.IsFileLocked(videoFile))
|
|
||||||
{
|
|
||||||
historyItem.Status = DownloadItemStatus.Downloading;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
historyItem.Status = DownloadItemStatus.Completed;
|
|
||||||
historyItem.RemainingTime = TimeSpan.Zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
historyItem.IsReadOnly = Settings.ReadOnly;
|
|
||||||
|
|
||||||
yield return historyItem;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -6,7 +6,7 @@
|
|||||||
using NzbDrone.Core.Validation;
|
using NzbDrone.Core.Validation;
|
||||||
using NzbDrone.Core.Validation.Paths;
|
using NzbDrone.Core.Validation.Paths;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Download.Clients.TorrentBlackhole
|
namespace NzbDrone.Core.Download.Clients.Blackhole
|
||||||
{
|
{
|
||||||
public class TorrentBlackholeSettingsValidator : AbstractValidator<TorrentBlackholeSettings>
|
public class TorrentBlackholeSettingsValidator : AbstractValidator<TorrentBlackholeSettings>
|
||||||
{
|
{
|
@ -13,13 +13,15 @@
|
|||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.RemotePathMappings;
|
using NzbDrone.Core.RemotePathMappings;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Download.Clients.UsenetBlackhole
|
namespace NzbDrone.Core.Download.Clients.Blackhole
|
||||||
{
|
{
|
||||||
public class UsenetBlackhole : UsenetClientBase<UsenetBlackholeSettings>
|
public class UsenetBlackhole : UsenetClientBase<UsenetBlackholeSettings>
|
||||||
{
|
{
|
||||||
private readonly IDiskScanService _diskScanService;
|
private readonly IScanWatchFolder _scanWatchFolder;
|
||||||
|
|
||||||
public UsenetBlackhole(IDiskScanService diskScanService,
|
public TimeSpan ScanGracePeriod { get; set; }
|
||||||
|
|
||||||
|
public UsenetBlackhole(IScanWatchFolder scanWatchFolder,
|
||||||
IHttpClient httpClient,
|
IHttpClient httpClient,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
IDiskProvider diskProvider,
|
IDiskProvider diskProvider,
|
||||||
@ -27,7 +29,9 @@ public UsenetBlackhole(IDiskScanService diskScanService,
|
|||||||
Logger logger)
|
Logger logger)
|
||||||
: base(httpClient, configService, diskProvider, remotePathMappingService, logger)
|
: base(httpClient, configService, diskProvider, remotePathMappingService, logger)
|
||||||
{
|
{
|
||||||
_diskScanService = diskScanService;
|
_scanWatchFolder = scanWatchFolder;
|
||||||
|
|
||||||
|
ScanGracePeriod = TimeSpan.FromSeconds(30);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override string AddFromNzbFile(RemoteEpisode remoteEpisode, string filename, byte[] fileContent)
|
protected override string AddFromNzbFile(RemoteEpisode remoteEpisode, string filename, byte[] fileContent)
|
||||||
@ -58,65 +62,22 @@ public override string Name
|
|||||||
|
|
||||||
public override IEnumerable<DownloadClientItem> GetItems()
|
public override IEnumerable<DownloadClientItem> GetItems()
|
||||||
{
|
{
|
||||||
foreach (var folder in _diskProvider.GetDirectories(Settings.WatchFolder))
|
foreach (var item in _scanWatchFolder.GetItems(Settings.WatchFolder, ScanGracePeriod))
|
||||||
{
|
{
|
||||||
var title = FileNameBuilder.CleanFileName(Path.GetFileName(folder));
|
yield return new DownloadClientItem
|
||||||
|
|
||||||
var files = _diskProvider.GetFiles(folder, SearchOption.AllDirectories);
|
|
||||||
|
|
||||||
var historyItem = new DownloadClientItem
|
|
||||||
{
|
{
|
||||||
DownloadClient = Definition.Name,
|
DownloadClient = Definition.Name,
|
||||||
DownloadId = Definition.Name + "_" + Path.GetFileName(folder) + "_" + _diskProvider.FolderGetCreationTime(folder).Ticks,
|
DownloadId = Definition.Name + "_" + item.DownloadId,
|
||||||
Category = "sonarr",
|
Category = "sonarr",
|
||||||
Title = title,
|
Title = item.Title,
|
||||||
|
|
||||||
TotalSize = files.Select(_diskProvider.GetFileSize).Sum(),
|
TotalSize = item.TotalSize,
|
||||||
|
RemainingTime = item.RemainingTime,
|
||||||
|
|
||||||
OutputPath = new OsPath(folder)
|
OutputPath = item.OutputPath,
|
||||||
|
|
||||||
|
Status = item.Status
|
||||||
};
|
};
|
||||||
|
|
||||||
if (files.Any(_diskProvider.IsFileLocked))
|
|
||||||
{
|
|
||||||
historyItem.Status = DownloadItemStatus.Downloading;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
historyItem.Status = DownloadItemStatus.Completed;
|
|
||||||
|
|
||||||
historyItem.RemainingTime = TimeSpan.Zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
yield return historyItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var videoFile in _diskScanService.GetVideoFiles(Settings.WatchFolder, false))
|
|
||||||
{
|
|
||||||
var title = FileNameBuilder.CleanFileName(Path.GetFileName(videoFile));
|
|
||||||
|
|
||||||
var historyItem = new DownloadClientItem
|
|
||||||
{
|
|
||||||
DownloadClient = Definition.Name,
|
|
||||||
DownloadId = Definition.Name + "_" + Path.GetFileName(videoFile) + "_" + _diskProvider.FileGetLastWrite(videoFile).Ticks,
|
|
||||||
Category = "sonarr",
|
|
||||||
Title = title,
|
|
||||||
|
|
||||||
TotalSize = _diskProvider.GetFileSize(videoFile),
|
|
||||||
|
|
||||||
OutputPath = new OsPath(videoFile)
|
|
||||||
};
|
|
||||||
|
|
||||||
if (_diskProvider.IsFileLocked(videoFile))
|
|
||||||
{
|
|
||||||
historyItem.Status = DownloadItemStatus.Downloading;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
historyItem.Status = DownloadItemStatus.Completed;
|
|
||||||
historyItem.RemainingTime = TimeSpan.Zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
yield return historyItem;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -5,7 +5,7 @@
|
|||||||
using NzbDrone.Core.Validation;
|
using NzbDrone.Core.Validation;
|
||||||
using NzbDrone.Core.Validation.Paths;
|
using NzbDrone.Core.Validation.Paths;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Download.Clients.UsenetBlackhole
|
namespace NzbDrone.Core.Download.Clients.Blackhole
|
||||||
{
|
{
|
||||||
public class UsenetBlackholeSettingsValidator : AbstractValidator<UsenetBlackholeSettings>
|
public class UsenetBlackholeSettingsValidator : AbstractValidator<UsenetBlackholeSettings>
|
||||||
{
|
{
|
@ -0,0 +1,22 @@
|
|||||||
|
using NzbDrone.Common.Disk;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Download.Clients.Blackhole
|
||||||
|
{
|
||||||
|
|
||||||
|
public class WatchFolderItem
|
||||||
|
{
|
||||||
|
public string DownloadId { get; set; }
|
||||||
|
public string Title { get; set; }
|
||||||
|
public long TotalSize { get; set; }
|
||||||
|
public TimeSpan? RemainingTime { get; set; }
|
||||||
|
public OsPath OutputPath { get; set; }
|
||||||
|
public DownloadItemStatus Status { get; set; }
|
||||||
|
|
||||||
|
public DateTime LastChanged { get; set; }
|
||||||
|
public string Hash { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -332,6 +332,8 @@
|
|||||||
<Compile Include="DiskSpace\DiskSpace.cs" />
|
<Compile Include="DiskSpace\DiskSpace.cs" />
|
||||||
<Compile Include="DiskSpace\DiskSpaceService.cs" />
|
<Compile Include="DiskSpace\DiskSpaceService.cs" />
|
||||||
<Compile Include="Download\CheckForFinishedDownloadCommand.cs" />
|
<Compile Include="Download\CheckForFinishedDownloadCommand.cs" />
|
||||||
|
<Compile Include="Download\Clients\Blackhole\ScanWatchFolder.cs" />
|
||||||
|
<Compile Include="Download\Clients\Blackhole\WatchFolderItem.cs" />
|
||||||
<Compile Include="Download\Clients\Deluge\Deluge.cs" />
|
<Compile Include="Download\Clients\Deluge\Deluge.cs" />
|
||||||
<Compile Include="Download\Clients\Deluge\DelugeError.cs" />
|
<Compile Include="Download\Clients\Deluge\DelugeError.cs" />
|
||||||
<Compile Include="Download\Clients\Deluge\DelugeException.cs" />
|
<Compile Include="Download\Clients\Deluge\DelugeException.cs" />
|
||||||
@ -411,8 +413,8 @@
|
|||||||
<Compile Include="Download\Clients\Sabnzbd\SabnzbdQueue.cs" />
|
<Compile Include="Download\Clients\Sabnzbd\SabnzbdQueue.cs" />
|
||||||
<Compile Include="Download\Clients\Sabnzbd\SabnzbdQueueItem.cs" />
|
<Compile Include="Download\Clients\Sabnzbd\SabnzbdQueueItem.cs" />
|
||||||
<Compile Include="Download\Clients\Sabnzbd\SabnzbdSettings.cs" />
|
<Compile Include="Download\Clients\Sabnzbd\SabnzbdSettings.cs" />
|
||||||
<Compile Include="Download\Clients\TorrentBlackhole\TorrentBlackhole.cs" />
|
<Compile Include="Download\Clients\Blackhole\TorrentBlackhole.cs" />
|
||||||
<Compile Include="Download\Clients\TorrentBlackhole\TorrentBlackholeSettings.cs" />
|
<Compile Include="Download\Clients\Blackhole\TorrentBlackholeSettings.cs" />
|
||||||
<Compile Include="Download\Clients\TorrentSeedConfiguration.cs" />
|
<Compile Include="Download\Clients\TorrentSeedConfiguration.cs" />
|
||||||
<Compile Include="Download\Clients\rTorrent\RTorrent.cs" />
|
<Compile Include="Download\Clients\rTorrent\RTorrent.cs" />
|
||||||
<Compile Include="Download\Clients\rTorrent\RTorrentPriority.cs" />
|
<Compile Include="Download\Clients\rTorrent\RTorrentPriority.cs" />
|
||||||
@ -427,8 +429,8 @@
|
|||||||
<Compile Include="Download\Clients\Transmission\TransmissionTorrent.cs" />
|
<Compile Include="Download\Clients\Transmission\TransmissionTorrent.cs" />
|
||||||
<Compile Include="Download\Clients\Transmission\TransmissionTorrentStatus.cs" />
|
<Compile Include="Download\Clients\Transmission\TransmissionTorrentStatus.cs" />
|
||||||
<Compile Include="Download\Clients\Transmission\TransmissionPriority.cs" />
|
<Compile Include="Download\Clients\Transmission\TransmissionPriority.cs" />
|
||||||
<Compile Include="Download\Clients\UsenetBlackhole\UsenetBlackhole.cs" />
|
<Compile Include="Download\Clients\Blackhole\UsenetBlackhole.cs" />
|
||||||
<Compile Include="Download\Clients\UsenetBlackhole\UsenetBlackholeSettings.cs" />
|
<Compile Include="Download\Clients\Blackhole\UsenetBlackholeSettings.cs" />
|
||||||
<Compile Include="Download\Clients\uTorrent\UTorrentPriority.cs" />
|
<Compile Include="Download\Clients\uTorrent\UTorrentPriority.cs" />
|
||||||
<Compile Include="Download\Clients\uTorrent\UTorrent.cs" />
|
<Compile Include="Download\Clients\uTorrent\UTorrent.cs" />
|
||||||
<Compile Include="Download\Clients\uTorrent\UTorrentProxy.cs" />
|
<Compile Include="Download\Clients\uTorrent\UTorrentProxy.cs" />
|
||||||
|
@ -80,6 +80,8 @@ public virtual void SetMock(Type type, Mock mock)
|
|||||||
{
|
{
|
||||||
if (_registeredMocks.ContainsKey(type) == false)
|
if (_registeredMocks.ContainsKey(type) == false)
|
||||||
_registeredMocks.Add(type, mock);
|
_registeredMocks.Add(type, mock);
|
||||||
|
if (mock != null)
|
||||||
|
_container.RegisterInstance(type, mock.Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void SetConstant<T>(T instance)
|
public virtual void SetConstant<T>(T instance)
|
||||||
|
Loading…
Reference in New Issue
Block a user