1
0
mirror of https://github.com/Radarr/Radarr.git synced 2026-03-29 18:15:37 -04:00

Compare commits

...

95 Commits

Author SHA1 Message Date
Taloth Saldono
7818f0c59b Fixed: Don't purge xem scene mapping cache when new series gets added. 2016-03-11 17:31:06 +01:00
Taloth Saldono
03e2adc332 Sort episodes in calendar by ep nr if airdate is the same. 2016-03-11 16:54:41 +01:00
Taloth Saldono
e6ab4196de Revert "Fixed: Sort episodes on the api by episode number when they air at the same time."
This reverts commit 9ffc0ec521.
2016-03-11 16:53:22 +01:00
Mark McDowall
f2784d3ec2 New: Trakt links on series details 2016-03-10 20:48:24 -08:00
Mark McDowall
ef3d508b31 Fixed: Anime season search won't search for missing episodes 2016-03-10 20:24:07 -08:00
Taloth Saldono
9ffc0ec521 Fixed: Sort episodes on the api by episode number when they air at the same time. 2016-03-06 00:43:04 +01:00
Mark McDowall
b598add64e Updated FluentValidation 2016-03-04 00:39:17 -08:00
Mark McDowall
47446515d1 Update CONTRIBUTING.md 2016-03-02 10:03:37 -08:00
Taloth Saldono
e5de7fb8cf Fixed: Don't trigger SceneMapping update and Housekeeping right on the startup event. 2016-03-01 23:50:09 +01:00
Taloth Saldono
55e870f295 Added version to logged exceptions. 2016-03-01 22:05:34 +01:00
Taloth Saldono
1485c83ab6 Don't hammer thexem, kthxbai. 2016-03-01 22:05:23 +01:00
Mark McDowall
e8d1623e96 Default Plex Media Server "Update Library" to true 2016-02-25 19:19:31 -08:00
Taloth Saldono
3bc6bf9e99 Don't die in MonoTorrent if nodes is an empty string. 2016-02-25 21:40:55 +01:00
Taloth Saldono
949d8bf49b Fixed: Warn if user has movie/date sorting enabled in Sabnzbd for the Sonarr category. 2016-02-25 20:39:42 +01:00
Taloth Saldono
c29e49da95 Clarified error message in MatchesFolderSpecification. 2016-02-25 19:44:29 +01:00
Taloth Saldono
79c565911c New: Changed the default of 'Use Hardlinks instead of Copy' to true. Most ppl seem to want that anyway. 2016-02-25 19:19:02 +01:00
Taloth Saldono
bb9a0371c5 Added TorrentRss test for ExtraTorrents, no other changes. 2016-02-25 19:18:46 +01:00
Taloth Saldono
e945231ab3 Fixed: Newznab should reject a Torznab feed. 2016-02-21 11:37:01 +01:00
Mark McDowall
c1298d162e Womble's has size parsing now 2016-02-18 18:39:23 -08:00
Taloth Saldono
f005edfcf0 Don't use Sonarr as ReleaseGroup if the pattern contains an advanced prefix/suffix. 2016-02-18 23:32:38 +01:00
Taloth Saldono
59c68ec6cc Write debug/trace log files separately to prevent trace from quickly rolling over debug. 2016-02-18 23:32:37 +01:00
Taloth Saldono
a5077b0b1b Replaced <removed> with (removed) for the log cleanser so it doesn't mess with forums. 2016-02-18 23:32:36 +01:00
Mark McDowall
a22c0499d5 Couple more anime version test cases 2016-02-17 23:06:44 -08:00
Mark McDowall
c38608e3cf Fixed Protocol returned for release/push endpoint 2016-02-17 20:26:37 -08:00
Taloth Saldono
3b57194d47 Fixed: Parses size in Wombles Description field so min/maxsize checks works on Wombles feed. 2016-02-17 23:22:22 +01:00
Taloth Saldono
21c901eab4 fixed failing torznab test 2016-02-17 21:52:55 +01:00
Taloth Saldono
9ad8311dd6 New: Use PageSize reported by newznab/torznab caps instead of hardcoded 100.
ref Jackett/Jackett#27
2016-02-17 21:23:27 +01:00
Taloth Saldono
df84028c90 Added DrunkenSlug and SimplyNZBs as Newznab presets. 2016-02-17 21:23:26 +01:00
Mark McDowall
7cb1e91ba1 Handle 1.1x version from Sabnzbd 2016-02-16 23:49:13 -08:00
Mark McDowall
974a7276c3 New: Explicitly enforce SABnzbd minimum version of 0.7.0 2016-02-16 22:40:12 -08:00
Mark McDowall
f0ca2bc11e Fixed: Don't collapse episode titles when episode titles contain Part x only 2016-02-16 21:28:32 -08:00
Mark McDowall
cb43888496 Fixed: Use Protocol over DownloadProtocol for ReleasePushModule
DownloadProtocol is still supported for backwards compatibility
2016-02-16 20:21:20 -08:00
Taloth Saldono
34d5fb1aa0 Fiddled with the Back to the Top button a bit so it's better visible on the white background, also only on widescreen now. 2016-02-15 22:56:10 +01:00
Taloth Saldono
72f0085ef7 Fixed: DownloadedEpisodesScan API command couldn't be used to process individual files. 2016-02-15 21:55:53 +01:00
Taloth Saldono
f25f5abced Cleaned up 2160p changes and added migration and tests.
Also reserved the quality ids for WEBRip etc.
2016-02-14 00:08:42 +01:00
Björn Dahlgren
94323f79e7 New: Added support for UltraHD (2160p) quality 2016-02-14 00:08:15 +01:00
Taloth Saldono
bdb1076100 Updated db migration testing framework so we only run migrations up to the one we're testing.
fixes #902
2016-02-13 23:21:32 +01:00
Mark McDowall
8818e39c63 Fixed: Daily + Standard with 3 digit episode numbers
Closes #1145
2016-02-11 18:46:32 -08:00
Taloth Saldono
6a90035a4c Updated NLog to v4.2.3. 2016-02-11 22:15:12 +01:00
Taloth Saldono
e01b2ef25c Fixed some compile warnings. 2016-02-11 22:11:53 +01:00
Taloth Saldono
91d91bc673 Fixed: Sample files of daily episodes should also be deleted after import. 2016-02-11 21:27:41 +01:00
Taloth Saldono
1c92ea58da Fixed: Replaced mono symlink resolve logic to better handle errors. 2016-02-11 21:12:42 +01:00
Taloth Saldono
bd6a38173e Add another nn preset. 2016-02-11 20:11:59 +01:00
Mark McDowall
5d05a85411 Delete the subfolder not the parent folder 2016-02-11 00:54:52 -08:00
Mark McDowall
1a5eafd2b1 New: Remove empty subfolders after renaming FileSetLastWriteTime
Closes #490
2016-02-11 00:38:44 -08:00
Mark McDowall
1603b06431 New: Prefer regular episodes over specials when absolute numbers conflict
Closes #676
2016-02-11 00:09:29 -08:00
Mark McDowall
2396af4589 New: Pushover Silent and Emergency priorities
Closes #878
2016-02-10 23:43:40 -08:00
Taloth Saldono
262b8daec1 Revert "Fixed regression, mono should resolve symlinks while trying to find out the available/total space."
This reverts commit d33efe59fc.
2016-02-11 01:52:47 +01:00
Taloth Saldono
d33efe59fc Fixed regression, mono should resolve symlinks while trying to find out the available/total space. 2016-02-11 01:14:16 +01:00
Taloth Saldono
5550565d6a Fixed: Manual Import didn't revert to parent folder when trying to parse series leading to issues with obfuscated releases. 2016-02-10 00:15:01 +01:00
Taloth Saldono
68540cb479 Certain log messages didn't include the exception. 2016-02-07 00:23:13 +01:00
Taloth Saldono
4038fa6907 Ignore -Obfuscated while parsing. 2016-02-06 10:43:56 +01:00
Taloth Saldono
f96f997506 Fixed: Handling xml responses containing invalid html entities.
fixes #1123
2016-02-05 20:08:54 +01:00
Taloth Saldono
4e84d1a17c Fixed: Throw more specific error when there's an issue with the curl root certificate bundle. 2016-02-02 22:11:39 +01:00
Taloth Saldono
97cdb6a4a5 Fixed: ZFS and other mounts now listed in the System page.
Will now also automatically revert to a fully transactional move/copy if the move is in our out of a cifs mount. (assuming the cifs mount can be detected)
2016-02-02 22:11:37 +01:00
Mark McDowall
f5b3d70641 Merge pull request #1112 from cturra/nzbplanet-api
updating nzbplanet.net api url to reflect recent change
2016-01-30 23:33:06 -08:00
cturra
db66d3da9e updating nzbplanet.net api url to reflect recent change 2016-01-30 21:27:18 -08:00
Taloth Saldono
c20e0667d4 Added additional tier to search for daily series type on BTN to find faux-daily series with SxxExx groups instead of date groups.
fixes #1111
2016-01-30 21:16:45 +01:00
Mark McDowall
4771b1c1b2 New: Parsing of XofY mini series format
Closes #1091
2016-01-30 11:16:59 -08:00
Mark McDowall
8e07a39ec0 Merge pull request #1095 from ta264/fix-build-sh
xbuild doesn't support /m parameter
2016-01-28 14:52:19 -08:00
Mark McDowall
9895b5bc1d Merge pull request #1100 from IvanBrazza/develop
Pushbullet: Source device support
2016-01-28 14:49:47 -08:00
Mark McDowall
e89a1bc0fb Fixed: Delete confirmation message for Restriction
Closes #1102
2016-01-28 14:04:10 -08:00
Ivan Brazza
9b0654c7f2 New: Setting Pushbullet source device 2016-01-28 21:33:11 +00:00
Mark McDowall
56da824e98 AutoComplete and file browser will show files when appropriate
Fixed: File browser for Custom Script shows files
Closes #1084
2016-01-27 19:24:41 -08:00
ta264
f84b7904e6 Fix: xbuild doesn't support /m parameter 2016-01-27 14:11:29 +00:00
Mark McDowall
9f523bb167 New: Prevent automatic update if UI folder is not writable 2016-01-24 19:22:07 -08:00
Taloth Saldono
f38d5de946 Fixed: Regression in parser incorrectly parsing S2015Exx.2015-01-01 notation.
fixes #1080
2016-01-21 22:43:48 +01:00
Taloth Saldono
de379b2e47 Do or do not, there is no try. 2016-01-21 21:10:22 +01:00
Taloth Saldono
64e90f35c8 Ensure rTorrent download is started even if the user doesn't have schedule=...,start_tied= in their rtorrent.rc. 2016-01-21 08:40:10 +01:00
Taloth Saldono
bbfe8c27c6 Fixed: Misleading error message when Kickass/Torrent Rss indexer returned invalid xml.
fixes #1058
2016-01-20 21:58:23 +01:00
Taloth Saldono
2f50074123 Fixed: Incorrect api error when calling /api/episode without seriesId queryparam.
fixes #1070
2016-01-20 21:58:02 +01:00
Taloth Saldono
5cfaed7b26 Fixed: Added support for Sabnzbd 0.8 history category queryparam.
fixes #1077
2016-01-20 21:57:40 +01:00
Taloth Saldono
0d19f645e8 Fixed: Don't apply indexer backoff on DNS and connection issues.
Fixes #751
2016-01-20 21:57:39 +01:00
Taloth Saldono
45d4371328 Fixed: Additional log cleanse Regex to keep even more sensitive information out of the logs.
fixes #1051
2016-01-20 21:57:10 +01:00
Taloth Saldono
889933cb41 New: Set full Download Directory in Transmission instead of just a Category.
fixes #744
2016-01-20 21:26:59 +01:00
Taloth Saldono
958b294152 Updated URL rewriter to handle torcache Referer weirdness. 2016-01-20 21:26:58 +01:00
Taloth Saldono
cf25097cd1 Fixed: Magnet downloads weren't being started on RTorrent. 2016-01-20 21:26:57 +01:00
Taloth Saldono
902e0dd5d6 Updated SharpZipLib to include patches made since the last official release. 2016-01-20 21:16:02 +01:00
Keivan Beigi
d943551a7f fixed build.sh 2016-01-16 16:39:45 -08:00
Keivan Beigi
46304b8a71 use build config to exclude xml doc rather than deleting them later 2016-01-16 16:36:40 -08:00
Keivan Beigi
6e2fc186ca added nuget.exe to tools 2016-01-16 16:19:28 -08:00
Keivan Beigi
845689401d removed msbuild integerated nuget restore 2016-01-16 16:17:36 -08:00
Keivan Beigi
4fb9cc5e8d cleanup app.manifest for Service helpers, upgraded compat to windows 8.1 2016-01-16 15:52:00 -08:00
Keivan Beigi
487581a01a apparently new compilers alraedy embed the app.manifest into the app, no need for mt.exe anymore 2016-01-16 15:51:26 -08:00
Keivan Beigi
2bc771d91e Merge pull request #1066 from pra85/2016
Update year range to 2016
2016-01-16 00:37:43 -08:00
Keivan Beigi
8bd7969328 cleanup 2016-01-16 00:36:43 -08:00
Keivan Beigi
5876ab487c fixed gulp build 2016-01-15 22:13:00 -08:00
Keivan Beigi
9c14ca0f39 Replaced build.ps1 with warning 2016-01-15 22:06:33 -08:00
Keivan Beigi
81ca352b2f smarted mdb generation 2016-01-15 21:50:09 -08:00
Keivan Beigi
0edfed5b95 upgraded pdb2mdb.exe to mono 4.2 Stable (4.2.1.102) 2016-01-15 21:50:09 -08:00
Prayag Verma
0ff053415c Update year range to 2016 2016-01-16 09:40:24 +05:30
Mark McDowall
a0ee607ae6 Remove double slash in NZBVortex add URL 2016-01-15 09:04:18 -08:00
Keivan Beigi
2723e2a7b8 faster test packaging in build.sh 2016-01-15 00:27:59 -08:00
Keivan Beigi
6e105ce2c6 upgraded nuget packages 2016-01-14 23:07:39 -08:00
Keivan Beigi
9fc7fceda4 updated npm packages 2016-01-14 18:56:14 -08:00
329 changed files with 3708 additions and 8057 deletions

View File

@@ -1,6 +1,6 @@
# How to Contribute #
We're always looking for people to help make Sonarr even better, there are a number of ways to contribute. To get started, <a href="http://www.clahub.com/agreements/NzbDrone/NzbDrone">sign the Contributor License Agreement</a>.
We're always looking for people to help make Sonarr even better, there are a number of ways to contribute.
## Documentation ##
Setup guides, FAQ, the more information we have on the wiki the better.

268
build.ps1
View File

@@ -1,267 +1 @@
$msBuild = 'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\msbuild.exe'
$outputFolder = '.\_output'
$outputFolderMono = '.\_output_mono'
$outputFolderOsx = '.\_output_osx'
$outputFolderOsxApp = '.\_output_osx_app'
$testPackageFolder = '.\_tests\'
$testSearchPattern = '*.Test\bin\x86\Release'
$sourceFolder = '.\src'
$updateFolder = $outputFolder + '\NzbDrone.Update'
$updateFolderMono = $outputFolderMono + '\NzbDrone.Update'
Function Build()
{
Write-Host "##teamcity[progressStart 'Build']"
$clean = $msbuild + " src\nzbdrone.sln /t:Clean /m"
$build = $msbuild + " src\nzbdrone.sln /p:Configuration=Release /p:Platform=x86 /t:Build /m"
if(Test-Path $outputFolder)
{
Remove-Item -Recurse -Force $outputFolder -ErrorAction Continue
}
Invoke-Expression $clean
CheckExitCode
Invoke-Expression $build
CheckExitCode
CleanFolder $outputFolder
AddJsonNet
Write-Host "Removing Mono.Posix.dll"
Remove-Item "$outputFolder\Mono.Posix.dll"
Get-ChildItem $outputFolder -File -Filter "*.dylib" -Recurse | foreach ($_) {Remove-Item $_.Fullname}
Write-Host "##teamcity[progressFinish 'Build']"
}
Function CleanFolder($path, $keepConfigFiles)
{
Write-Host Removing XMLDoc files
get-childitem $path -File -Filter *.xml -Recurse | foreach ($_) {
$filename = $_.FullName
$exeFilename = $filename -replace "xml", "exe"
$dllFilename = $filename -replace "xml", "dll"
if (Test-Path $exeFilename) {
remove-item $_.fullname
}
if (Test-Path $dllFilename) {
remove-item $_.fullname
}
}
get-childitem $path -File -Filter *.transform -Recurse | foreach ($_) {remove-item $_.fullname}
if($keepConfigFiles -ne $true)
{
get-childitem $path -File -Filter *.dll.config -Recurse | foreach ($_) {remove-item $_.fullname}
}
Write-Host Removing FluentValidation.Resources files
get-childitem $path -File -Filter FluentValidation.resources.dll -recurse | foreach ($_) {remove-item $_.fullname}
get-childitem $path -File -Filter app.config -Recurse | foreach ($_) {remove-item $_.fullname}
Write-Host Removing .less files
get-childitem $path -File -Filter *.less -Recurse | foreach ($_) {remove-item $_.fullname}
Write-Host Removing vshost files
get-childitem $path -File -Filter *.vshost.exe -Recurse | foreach ($_) {remove-item $_.fullname}
if(Test-Path $$path\NuGet)
{
Write-Host Removing NuGet
Remove-Item -Recurse -Force "$path\NuGet"
}
Write-Host Removing Empty folders
while (Get-ChildItem $path -recurse | where {!@(Get-ChildItem -force $_.fullname)} | Test-Path)
{
Get-ChildItem $path -Directory -recurse | where {!@(Get-ChildItem -force $_.fullname)} | Remove-Item
}
}
Function PackageMono()
{
Write-Host "##teamcity[progressStart 'Creating Mono Package']"
if(Test-Path $outputFolderMono)
{
Remove-Item -Recurse -Force $outputFolderMono -ErrorAction Continue
}
Copy-Item $outputFolder $outputFolderMono -recurse
Write-Host Creating MDBs
get-childitem $outputFolderMono -File -Include @("*.exe", "*.dll") -Exclude @("MediaInfo.dll", "sqlite3.dll") -Recurse | foreach ($_) {
Write-Host "Creating .mdb for $_"
& "tools\pdb2mdb\pdb2mdb.exe" $_.fullname
}
Write-Host Removing PDBs
get-childitem $outputFolderMono -File -Filter *.pdb -Recurse | foreach ($_) {remove-item $_.fullname}
Write-Host Removing Service helpers
get-childitem $outputFolderMono -File -Filter ServiceUninstall.* -Recurse | foreach ($_) {remove-item $_.fullname}
get-childitem $outputFolderMono -File -Filter ServiceInstall.* -Recurse | foreach ($_) {remove-item $_.fullname}
Write-Host Removing native windows binaries Sqlite, MediaInfo
get-childitem $outputFolderMono -File -Filter sqlite3.* -Recurse | foreach ($_) {remove-item $_.fullname}
get-childitem $outputFolderMono -File -Filter MediaInfo.* -Recurse | foreach ($_) {remove-item $_.fullname}
Write-Host "Adding NzbDrone.Core.dll.config (for dllmap)"
Copy-Item "$sourceFolder\NzbDrone.Core\NzbDrone.Core.dll.config" $outputFolderMono
Write-Host "Adding CurlSharp.dll.config (for dllmap)"
Copy-Item "$sourceFolder\NzbDrone.Common\CurlSharp.dll.config" $outputFolderMono
Write-Host Renaming NzbDrone.Console.exe to NzbDrone.exe
Get-ChildItem $outputFolderMono -File -Filter "NzbDrone.exe*" -Recurse | foreach ($_) {remove-item $_.fullname}
Write-Host Removing NzbDrone.Windows
get-childitem $outputFolderMono -File -Filter NzbDrone.Windows.* -Recurse | foreach ($_) {remove-item $_.fullname}
Get-ChildItem $outputFolderMono -File -Filter "NzbDrone.Console.exe*" -Recurse | foreach ($_) {
$newName = $_.fullname -Replace ".Console",""
Rename-Item $_.fullname $newName
}
Write-Host Adding NzbDrone.Mono to UpdatePackage
Copy-Item $outputFolderMono\* $updateFolderMono -Filter NzbDrone.Mono.*
Write-Host "##teamcity[progressFinish 'Creating Mono Package']"
}
Function PackageOsx()
{
Write-Host "##teamcity[progressStart 'Creating OS X Package']"
if(Test-Path $outputFolderOsx)
{
Remove-Item -Recurse -Force $outputFolderOsx -ErrorAction Continue
}
Copy-Item $outputFolderMono $outputFolderOsx -recurse
Write-Host "Adding sqlite dylibs"
Copy-Item "$sourceFolder\Libraries\sqlite\*.dylib" "$outputFolderOsx"
Write-Host "Adding MediaInfo dylib"
Copy-Item "$sourceFolder\Libraries\MediaInfo\*.dylib" "$outputFolderOsx"
Write-Host "Adding Startup script"
Copy-Item .\osx\Sonarr "$outputFolderOsx"
Write-Host "##teamcity[progressFinish 'Creating OS X Package']"
}
Function PackageOsxApp()
{
Write-Host "##teamcity[progressStart 'Creating OS X App Package']"
if(Test-Path $outputFolderOsxApp)
{
Remove-Item -Recurse -Force $outputFolderOsxApp -ErrorAction Continue
}
Copy-Item .\osx\Sonarr.app $outputFolderOsxApp\Sonarr.app -recurse
Copy-Item $outputFolderOsx $outputFolderOsxApp\Sonarr.app\Contents\MacOS -recurse
Write-Host "##teamcity[progressFinish 'Creating OS X App Package']"
}
Function AddJsonNet()
{
get-childitem $outputFolder -File -Filter Newtonsoft.Json.* -Recurse | foreach ($_) {remove-item $_.fullname}
Copy-Item .\src\packages\Newtonsoft.Json.*.*\lib\net35\*.dll -Destination $outputFolder
Copy-Item .\src\packages\Newtonsoft.Json.*.*\lib\net35\*.dll -Destination $outputFolder\NzbDrone.Update
}
Function PackageTests()
{
Write-Host Packaging Tests
Write-Host "##teamcity[progressStart 'Creating Test Package']"
if(Test-Path $testPackageFolder)
{
Remove-Item -Recurse -Force $testPackageFolder -ErrorAction Continue
}
Get-ChildItem -Recurse -Directory | Where-Object {$_.FullName -like $testSearchPattern} | foreach($_){
Copy-Item -Recurse ($_.FullName + "\*") $testPackageFolder -ErrorAction Ignore
}
.\src\.nuget\NuGet.exe install NUnit.Runners -Version 2.6.1 -Output $testPackageFolder
Copy-Item $outputFolder\*.dll -Destination $testPackageFolder -Force
Copy-Item $outputFolder\*.pdb -Destination $testPackageFolder -Force
Copy-Item .\*.sh -Destination $testPackageFolder -Force
Write-Host Creating MDBs for tests
get-childitem $testPackageFolder -File -Include @("*.exe", "*.dll") -Exclude @("MediaInfo.dll", "sqlite3.dll") -Recurse | foreach ($_) {
Write-Host "Creating .mdb for $_"
& "tools\pdb2mdb\pdb2mdb.exe" $_.fullname
}
get-childitem $testPackageFolder -File -Filter *log.config | foreach ($_) {remove-item $_.fullname}
CleanFolder $testPackageFolder $true
Write-Host "Adding NzbDrone.Core.dll.config (for dllmap)"
Copy-Item "$sourceFolder\NzbDrone.Core\NzbDrone.Core.dll.config" -Destination $testPackageFolder -Force
Write-Host "Copying CurlSharp libraries"
Copy-Item $sourceFolder\ExternalModules\CurlSharp\libs\i386\* $testPackageFolder
Write-Host "##teamcity[progressFinish 'Creating Test Package']"
}
Function RunGulp()
{
Write-Host "##teamcity[progressStart 'Running Gulp']"
Invoke-Expression 'npm install'
CheckExitCode
Invoke-Expression 'gulp build' -ErrorAction Continue -Verbose
CheckExitCode
Invoke-Expression 'gulp build --phantom' -ErrorAction Continue -Verbose
CheckExitCode
Write-Host "##teamcity[progressFinish 'Running Gulp']"
}
Function CheckExitCode()
{
if ($lastexitcode -ne 0)
{
Write-Host $errorMessage
exit 1
}
}
Function CleanupWindowsPackage()
{
Write-Host Removing NzbDrone.Mono
get-childitem $outputFolder -File -Filter NzbDrone.Mono.* -Recurse | foreach ($_) {remove-item $_.fullname}
Write-Host Adding NzbDrone.Windows to UpdatePackage
Copy-Item $outputFolder\* $updateFolder -Filter NzbDrone.Windows.*
}
Build
RunGulp
PackageMono
PackageOsx
PackageOsxApp
PackageTests
CleanupWindowsPackage
Write-Warning "DEPRECATED -- Please use build.sh instead."

View File

@@ -5,11 +5,13 @@ outputFolderMono='./_output_mono'
outputFolderOsx='./_output_osx'
outputFolderOsxApp='./_output_osx_app'
testPackageFolder='./_tests/'
testSearchPattern='*.Test/bin/x86/Release/*'
testSearchPattern='*.Test/bin/x86/Release'
sourceFolder='./src'
slnFile=$sourceFolder/NzbDrone.sln
updateFolder=$outputFolder/NzbDrone.Update
updateFolderMono=$outputFolderMono/NzbDrone.Update
nuget='tools/nuget/nuget.exe';
CheckExitCode()
{
"$@"
@@ -26,14 +28,6 @@ CleanFolder()
local path=$1
local keepConfigFiles=$2
echo "Removing XMLDoc files"
local xmlfiles=( $(find $path -name "*.xml") )
for filename in "${xmlfiles[@]}"
do
if [ -e ${filename%.xml}.dll ] || [ -e ${filename%.xml}.exe ] ; then
rm $filename
fi
done
find $path -name "*.transform" -exec rm "{}" \;
@@ -51,10 +45,8 @@ CleanFolder()
echo "Removing vshost files"
find $path -name "*.vshost.exe" -exec rm "{}" \;
if [ -d $path/NuGet ] ; then
echo "Removing NuGet"
rm -rf $path/NuGet
fi
echo "Removing dylib files"
find $path -name "*.dylib" -exec rm "{}" \;
echo "Removing Empty folders"
find $path -depth -empty -type d -exec rm -r "{}" \;
@@ -72,15 +64,17 @@ AddJsonNet()
BuildWithMSBuild()
{
export PATH=$msBuild:$PATH
CheckExitCode MSBuild.exe $sourceFolder/NzbDrone.sln //t:Clean //m
CheckExitCode MSBuild.exe $sourceFolder/NzbDrone.sln //p:Configuration=Release //p:Platform=x86 //t:Build //m
CheckExitCode MSBuild.exe $slnFile //t:Clean //m
$nuget restore $slnFile
CheckExitCode MSBuild.exe $slnFile //p:Configuration=Release //p:Platform=x86 //t:Build //m //p:AllowedReferenceRelatedFileExtensions=.pdb
}
BuildWithXbuild()
{
export MONO_IOMAP=case
CheckExitCode xbuild /t:Clean $sourceFolder/NzbDrone.sln
CheckExitCode xbuild /p:Configuration=Release /p:Platform=x86 /t:Build $sourceFolder/NzbDrone.sln
CheckExitCode xbuild /t:Clean $slnFile
mono $nuget restore $slnFile
CheckExitCode xbuild /p:Configuration=Release /p:Platform=x86 /t:Build /p:AllowedReferenceRelatedFileExtensions=.pdb $slnFile
}
Build()
@@ -94,9 +88,9 @@ Build()
else
BuildWithXbuild
fi
CleanFolder $outputFolder false
AddJsonNet
echo "Removing Mono.Posix.dll"
@@ -107,11 +101,12 @@ Build()
RunGulp()
{
echo "##teamcity[progressStart 'Running Gulp']"
echo "##teamcity[progressStart 'npm install']"
CheckExitCode npm install
CheckExitCode gulp build
echo "##teamcity[progressFinish 'npm install']"
echo "##teamcity[progressStart 'Running Gulp']"
CheckExitCode gulp build
echo "##teamcity[progressFinish 'Running Gulp']"
}
@@ -119,7 +114,16 @@ CreateMdbs()
{
local path=$1
if [ $runtime = "dotnet" ] ; then
find $path \( -name "*.exe" -o -name "*.dll" \) -not -name "MediaInfo.dll" -not -name "sqlite3.dll" -exec tools/pdb2mdb/pdb2mdb.exe "{}" \;
local pdbFiles=( $(find $path -name "*.pdb") )
for filename in "${pdbFiles[@]}"
do
if [ -e ${filename%.pdb}.dll ] ; then
tools/pdb2mdb/pdb2mdb.exe ${filename%.pdb}.dll
fi
if [ -e ${filename%.pdb}.exe ] ; then
tools/pdb2mdb/pdb2mdb.exe ${filename%.pdb}.exe
fi
done
fi
}
@@ -160,6 +164,8 @@ PackageMono()
echo "Adding NzbDrone.Mono to UpdatePackage"
cp $outputFolderMono/NzbDrone.Mono.* $updateFolderMono
echo "##teamcity[progressFinish 'Creating Mono Package']"
}
PackageOsx()
@@ -199,13 +205,12 @@ PackageTests()
rm -rf $testPackageFolder
mkdir $testPackageFolder
find . -maxdepth 6 -path $testSearchPattern -exec cp -r "{}" $testPackageFolder \;
find $sourceFolder -path $testSearchPattern -exec cp -r -u -T "{}" $testPackageFolder \;
if [ $runtime = "dotnet" ] ; then
$sourceFolder/.nuget/NuGet.exe install NUnit.Runners -Version 2.6.1 -Output $testPackageFolder
cp $outputFolder/*.pdb $testPackageFolder
$nuget install NUnit.Runners -Version 2.6.1 -Output $testPackageFolder
else
mono $sourceFolder/.nuget/NuGet.exe install NUnit.Runners -Version 2.6.1 -Output $testPackageFolder
mono $nuget install NUnit.Runners -Version 2.6.1 -Output $testPackageFolder
fi
cp $outputFolder/*.dll $testPackageFolder

2
debian/copyright vendored
View File

@@ -3,7 +3,7 @@ Upstream-Name: nzbdrone
Source: https://github.com/Sonarr/Sonarr
Files: *
Copyright: 2010-2014 Sonarr <hello@sonarr.tv>
Copyright: 2010-2016 Sonarr <hello@sonarr.tv>
License: GPL-3.0+

View File

@@ -7,7 +7,6 @@ var autoprefixer = require('autoprefixer-core');
var livereload = require('gulp-livereload');
var print = require('gulp-print');
var phantom = require('./phantom');
var paths = require('./paths');
var errorHandler = require('./errorHandler');
@@ -29,14 +28,6 @@ gulp.task('less', function() {
paths.src.root + 'System/Info/info.less'
];
if (phantom) {
src = [
paths.src.content + 'Bootstrap/bootstrap.less',
paths.src.content + 'Vendor/vendor.less',
paths.src.content + 'sonarr.less'
];
}
return gulp.src(src)
.pipe(print())
.pipe(sourcemaps.init())

View File

@@ -1,5 +1,3 @@
var phantom = require('./phantom');
var paths = {
src : {
root : './src/UI/',
@@ -20,26 +18,4 @@ var paths = {
}
};
if (phantom) {
paths = {
src : {
root : './UI.Phantom/',
templates : './UI.Phantom/**/*.hbs',
html : './UI.Phantom/*.html',
partials : './UI.Phantom/**/*Partial.hbs',
scripts : './UI.Phantom/**/*.js',
less : ['./UI.Phantom/**/*.less'],
content : './UI.Phantom/Content/',
images : './UI.Phantom/Content/Images/**/*',
exclude : {
libs : '!./UI.Phantom/JsLibraries/**'
}
},
dest : {
root : './_output/UI.Phantom/',
content : './_output/UI.Phantom/Content/'
}
};
}
module.exports = paths;

View File

@@ -1,14 +0,0 @@
// Switch to phantom.
// Example:
// gulp --phantom
var phantom = false;
process.argv.forEach(function(val, index, array) {
if (val === '--phantom') {
phantom = true;
}
});
console.log('Phantom:', phantom);
module.exports = phantom;

View File

@@ -45,7 +45,7 @@ Sonarr is a PVR for Usenet and BitTorrent users. It can monitor multiple RSS fee
### License ###
* [GNU GPL v3](http://www.gnu.org/licenses/gpl.html)
Copyright 2010-2015
Copyright 2010-2016
### Sponsors ###

View File

@@ -1,17 +0,0 @@
Param(
[Parameter(Mandatory=$true, Position=0, HelpMessage="A branch name is #requires required")]
[string]$branch,
[Parameter(Mandatory=$true, Position=1, HelpMessage="A version is required")]
[string]$version
)
if ($branch -eq "<default>")
{
$branch = "teamcity";
}
Write-Host $branch;
Write-Host $version;
Write-Host "NzbDrone.$branch.$version.zip";
Rename-Item "nzbdrone.zip" "NzbDrone.$branch.$version.zip"

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<solution>
<add key="disableSourceControlIntegration" value="true" />
</solution>
</configuration>

Binary file not shown.

View File

@@ -1,136 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">$(MSBuildProjectDirectory)\..\</SolutionDir>
<!-- Enable the restore command to run before builds -->
<RestorePackages Condition=" '$(RestorePackages)' == '' ">false</RestorePackages>
<!-- Property that enables building a package from a project -->
<BuildPackage Condition=" '$(BuildPackage)' == '' ">false</BuildPackage>
<!-- Determines if package restore consent is required to restore packages -->
<RequireRestoreConsent Condition=" '$(RequireRestoreConsent)' != 'false' ">true</RequireRestoreConsent>
<!-- Download NuGet.exe if it does not already exist -->
<DownloadNuGetExe Condition=" '$(DownloadNuGetExe)' == '' ">false</DownloadNuGetExe>
</PropertyGroup>
<ItemGroup Condition=" '$(PackageSources)' == '' ">
<!-- Package sources used to restore packages. By default, registered sources under %APPDATA%\NuGet\NuGet.Config will be used -->
<!-- The official NuGet package source (https://www.nuget.org/api/v2/) will be excluded if package sources are specified and it does not appear in the list -->
<!--
<PackageSource Include="https://www.nuget.org/api/v2/" />
<PackageSource Include="https://my-nuget-source/nuget/" />
-->
</ItemGroup>
<PropertyGroup Condition=" '$(OS)' == 'Windows_NT'">
<!-- Windows specific commands -->
<NuGetToolsPath>$([System.IO.Path]::Combine($(SolutionDir), ".nuget"))</NuGetToolsPath>
<PackagesConfig>$([System.IO.Path]::Combine($(ProjectDir), "packages.config"))</PackagesConfig>
</PropertyGroup>
<PropertyGroup Condition=" '$(OS)' != 'Windows_NT'">
<!-- We need to launch nuget.exe with the mono command if we're not on windows -->
<NuGetToolsPath>$(SolutionDir).nuget</NuGetToolsPath>
<PackagesConfig>packages.config</PackagesConfig>
</PropertyGroup>
<PropertyGroup>
<!-- NuGet command -->
<NuGetExePath Condition=" '$(NuGetExePath)' == '' ">$(NuGetToolsPath)\NuGet.exe</NuGetExePath>
<PackageSources Condition=" $(PackageSources) == '' ">@(PackageSource)</PackageSources>
<NuGetCommand Condition=" '$(OS)' == 'Windows_NT'">"$(NuGetExePath)"</NuGetCommand>
<NuGetCommand Condition=" '$(OS)' != 'Windows_NT' ">mono --runtime=v4.0.30319 $(NuGetExePath)</NuGetCommand>
<PackageOutputDir Condition="$(PackageOutputDir) == ''">$(TargetDir.Trim('\\'))</PackageOutputDir>
<RequireConsentSwitch Condition=" $(RequireRestoreConsent) == 'true' ">-RequireConsent</RequireConsentSwitch>
<NonInteractiveSwitch Condition=" '$(VisualStudioVersion)' != '' AND '$(OS)' == 'Windows_NT' ">-NonInteractive</NonInteractiveSwitch>
<PaddedSolutionDir Condition=" '$(OS)' == 'Windows_NT'">"$(SolutionDir) "</PaddedSolutionDir>
<PaddedSolutionDir Condition=" '$(OS)' != 'Windows_NT' ">"$(SolutionDir)"</PaddedSolutionDir>
<!-- Commands -->
<RestoreCommand>$(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir)</RestoreCommand>
<BuildCommand>$(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols</BuildCommand>
<!-- We need to ensure packages are restored prior to assembly resolve -->
<BuildDependsOn Condition="$(RestorePackages) == 'true'">
RestorePackages;
$(BuildDependsOn);
</BuildDependsOn>
<!-- Make the build depend on restore packages -->
<BuildDependsOn Condition="$(BuildPackage) == 'true'">
$(BuildDependsOn);
BuildPackage;
</BuildDependsOn>
</PropertyGroup>
<Target Name="CheckPrerequisites">
<!-- Raise an error if we're unable to locate nuget.exe -->
<Error Condition="'$(DownloadNuGetExe)' != 'true' AND !Exists('$(NuGetExePath)')" Text="Unable to locate '$(NuGetExePath)'" />
<!--
Take advantage of MsBuild's build dependency tracking to make sure that we only ever download nuget.exe once.
This effectively acts as a lock that makes sure that the download operation will only happen once and all
parallel builds will have to wait for it to complete.
-->
<MsBuild Targets="_DownloadNuGet" Projects="$(MSBuildThisFileFullPath)" Properties="Configuration=NOT_IMPORTANT;DownloadNuGetExe=$(DownloadNuGetExe)" />
</Target>
<Target Name="_DownloadNuGet">
<DownloadNuGet OutputFilename="$(NuGetExePath)" Condition=" '$(DownloadNuGetExe)' == 'true' AND !Exists('$(NuGetExePath)')" />
</Target>
<Target Name="RestorePackages" DependsOnTargets="CheckPrerequisites">
<Exec Command="$(RestoreCommand)"
Condition="'$(OS)' != 'Windows_NT' And Exists('$(PackagesConfig)')" />
<Exec Command="$(RestoreCommand)"
LogStandardErrorAsError="true"
Condition="'$(OS)' == 'Windows_NT' And Exists('$(PackagesConfig)')" />
</Target>
<Target Name="BuildPackage" DependsOnTargets="CheckPrerequisites">
<Exec Command="$(BuildCommand)"
Condition=" '$(OS)' != 'Windows_NT' " />
<Exec Command="$(BuildCommand)"
LogStandardErrorAsError="true"
Condition=" '$(OS)' == 'Windows_NT' " />
</Target>
<UsingTask TaskName="DownloadNuGet" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<OutputFilename ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Reference Include="System.Core" />
<Using Namespace="System" />
<Using Namespace="System.IO" />
<Using Namespace="System.Net" />
<Using Namespace="Microsoft.Build.Framework" />
<Using Namespace="Microsoft.Build.Utilities" />
<Code Type="Fragment" Language="cs">
<![CDATA[
try {
OutputFilename = Path.GetFullPath(OutputFilename);
Log.LogMessage("Downloading latest version of NuGet.exe...");
WebClient webClient = new WebClient();
webClient.DownloadFile("https://www.nuget.org/nuget.exe", OutputFilename);
return true;
}
catch (Exception ex) {
Log.LogErrorFromException(ex);
return false;
}
]]>
</Code>
</Task>
</UsingTask>
</Project>

Binary file not shown.

View File

@@ -1,9 +0,0 @@
<?xml version ="1.0"?>
<!-- This allows mt.exe to run on machines with the CLR v4 installed but not 1.1 or 2.0 -->
<configuration>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0"/>
<supportedRuntime version="v2.0.50727"/>
<supportedRuntime version="v1.1.4322"/>
</startup>
</configuration>

View File

@@ -296,7 +296,7 @@ namespace LogentriesCore
WriteDebugMessages("HostName parameter is not defined - trying to get it from System.Environment.MachineName");
m_HostName = "HostName=" + System.Environment.MachineName + " ";
}
catch (InvalidOperationException ex)
catch (InvalidOperationException)
{
// Cannot get host name automatically, so assume that HostName is not used
// and log message is sent without it.

View File

@@ -73,13 +73,6 @@
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">

View File

@@ -51,8 +51,9 @@
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="NLog">
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.2.3\lib\net40\NLog.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
@@ -79,19 +80,13 @@
</ItemGroup>
<ItemGroup>
<None Include="fastJSON\license.txt" />
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="NLog" version="2.1.0" targetFramework="net40" />
</packages>
<package id="NLog" version="4.2.3" targetFramework="net40" />
</packages>

View File

@@ -144,7 +144,6 @@
<PreBuildEvent>
</PreBuildEvent>
</PropertyGroup>
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">

View File

@@ -276,10 +276,9 @@
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="AfterBuild">
</Target>
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
</Target>
-->
</Project>

View File

@@ -102,7 +102,6 @@
</ItemGroup>
<Import Project="..\Common\Microsoft.AspNet.SignalR.targets" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
@@ -110,4 +109,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>

View File

@@ -774,7 +774,8 @@ namespace MonoTorrent
break;
case ("nodes"):
this.nodes = (BEncodedList)keypair.Value;
if (keypair.Value.ToString().Length != 0)
this.nodes = (BEncodedList)keypair.Value;
break;
case ("comment.utf-8"):

View File

@@ -38,12 +38,12 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="FluentAssertions, Version=3.4.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<HintPath>..\packages\FluentAssertions.3.4.0\lib\net40\FluentAssertions.dll</HintPath>
<Reference Include="FluentAssertions, Version=4.2.1.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<HintPath>..\packages\FluentAssertions.4.2.1\lib\net40\FluentAssertions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="FluentAssertions.Core, Version=3.4.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<HintPath>..\packages\FluentAssertions.3.4.0\lib\net40\FluentAssertions.Core.dll</HintPath>
<Reference Include="FluentAssertions.Core, Version=4.2.1.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<HintPath>..\packages\FluentAssertions.4.2.1\lib\net40\FluentAssertions.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="nunit.framework, Version=2.6.3.13283, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
@@ -104,7 +104,6 @@
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
@@ -112,4 +111,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="FluentAssertions" version="3.4.0" targetFramework="net40" />
<package id="FluentAssertions" version="4.2.1" targetFramework="net40" />
<package id="Moq" version="4.0.10827" />
<package id="NBuilder" version="3.0.1.1" targetFramework="net40" />
<package id="NUnit" version="2.6.3" targetFramework="net40" />
<package id="ValueInjecter" version="2.3.3" targetFramework="net40" />
</packages>
</packages>

View File

@@ -52,16 +52,16 @@ namespace NzbDrone.Api.EpisodeFiles
private List<EpisodeFileResource> GetEpisodeFiles()
{
var seriesId = (int?)Request.Query.SeriesId;
if (seriesId == null)
if (!Request.Query.SeriesId.HasValue)
{
throw new BadRequestException("seriesId is missing");
}
var series = _seriesService.GetSeries(seriesId.Value);
var seriesId = (int)Request.Query.SeriesId;
return _mediaFileService.GetFilesBySeries(seriesId.Value)
var series = _seriesService.GetSeries(seriesId);
return _mediaFileService.GetFilesBySeries(seriesId)
.Select(f => MapToResource(series, f)).ToList();
}

View File

@@ -20,14 +20,14 @@ namespace NzbDrone.Api.Episodes
private List<EpisodeResource> GetEpisodes()
{
var seriesId = (int?)Request.Query.SeriesId;
if (seriesId == null)
if (!Request.Query.SeriesId.HasValue)
{
throw new BadRequestException("seriesId is missing");
}
var resources = ToListResource(_episodeService.GetEpisodeBySeries(seriesId.Value));
var seriesId = (int)Request.Query.SeriesId;
var resources = ToListResource(_episodeService.GetEpisodeBySeries(seriesId));
return resources;
}

View File

@@ -18,18 +18,13 @@ namespace NzbDrone.Api.Episodes
private List<RenameEpisodeResource> GetEpisodes()
{
int seriesId;
if (Request.Query.SeriesId.HasValue)
{
seriesId = (int)Request.Query.SeriesId;
}
else
if (!Request.Query.SeriesId.HasValue)
{
throw new BadRequestException("seriesId is missing");
}
var seriesId = (int)Request.Query.SeriesId;
if (Request.Query.SeasonNumber.HasValue)
{
var seasonNumber = (int)Request.Query.SeasonNumber;

View File

@@ -26,7 +26,7 @@ namespace NzbDrone.Api.ErrorManagement
if (apiException != null)
{
_logger.WarnException("API Error", apiException);
_logger.Warn(apiException, "API Error");
return apiException.ToErrorResponse();
}
@@ -65,10 +65,10 @@ namespace NzbDrone.Api.ErrorManagement
var sqlErrorMessage = string.Format("[{0} {1}]", context.Request.Method, context.Request.Path);
_logger.ErrorException(sqlErrorMessage, sqLiteException);
_logger.Error(sqLiteException, sqlErrorMessage);
}
_logger.FatalException("Request Failed", exception);
_logger.Fatal(exception, "Request Failed");
return new ErrorModel
{

View File

@@ -60,7 +60,7 @@ namespace NzbDrone.Api.Extensions.Pipelines
catch (Exception ex)
{
_logger.ErrorException("Unable to gzip response", ex);
_logger.Error(ex, "Unable to gzip response");
throw;
}
}

View File

@@ -68,7 +68,7 @@ namespace NzbDrone.Api.Indexers
}
catch (ReleaseDownloadException ex)
{
_logger.ErrorException(ex.Message, ex);
_logger.Error(ex, ex.Message);
throw new NzbDroneClientException(HttpStatusCode.Conflict, "Getting release from indexer failed");
}
@@ -96,7 +96,7 @@ namespace NzbDrone.Api.Indexers
}
catch (Exception ex)
{
_logger.ErrorException("Episode search failed: " + ex.Message, ex);
_logger.Error(ex, "Episode search failed: " + ex.Message);
}
return new List<ReleaseResource>();

View File

@@ -9,6 +9,7 @@ using NzbDrone.Core.Parser.Model;
using NzbDrone.Api.Mapping;
using NzbDrone.Api.Extensions;
using NLog;
using NzbDrone.Core.Indexers;
namespace NzbDrone.Api.Indexers
{
@@ -30,7 +31,7 @@ namespace NzbDrone.Api.Indexers
PostValidator.RuleFor(s => s.Title).NotEmpty();
PostValidator.RuleFor(s => s.DownloadUrl).NotEmpty();
PostValidator.RuleFor(s => s.DownloadProtocol).NotEmpty();
PostValidator.RuleFor(s => s.Protocol).NotEmpty();
PostValidator.RuleFor(s => s.PublishDate).NotEmpty();
}
@@ -38,11 +39,14 @@ namespace NzbDrone.Api.Indexers
{
_logger.Info("Release pushed: {0} - {1}", release.Title, release.DownloadUrl);
var info = release.InjectTo<ReleaseInfo>();
var info = release.Protocol == DownloadProtocol.Usenet ?
release.InjectTo<ReleaseInfo>() :
release.InjectTo<TorrentInfo>();
info.Guid = "PUSH-" + info.DownloadUrl;
var decisions = _downloadDecisionMaker.GetRssDecision(new List<ReleaseInfo> { info });
var processed = _downloadDecisionProcessor.ProcessDecisions(decisions);
_downloadDecisionProcessor.ProcessDecisions(decisions);
return MapDecisions(decisions).First().AsResponse();
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using NzbDrone.Api.REST;
using NzbDrone.Core.Parser;
using NzbDrone.Core.Qualities;
@@ -48,8 +49,25 @@ namespace NzbDrone.Api.Indexers
public int? Leechers { get; set; }
public DownloadProtocol Protocol { get; set; }
//TODO: besides a test I don't think this is used...
public DownloadProtocol DownloadProtocol { get; set; }
// TODO: Remove in v3
// Used to support the original Release Push implementation
// JsonIgnore so we don't serialize it, but can still parse it
[JsonIgnore]
public DownloadProtocol DownloadProtocol
{
get
{
return Protocol;
}
set
{
if (value > 0 && Protocol == 0)
{
Protocol = value;
}
}
}
public bool IsDaily { get; set; }
public bool IsAbsoluteNumbering { get; set; }

View File

@@ -40,9 +40,9 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="FluentValidation, Version=5.5.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\FluentValidation.5.5.0.0\lib\Net40\FluentValidation.dll</HintPath>
<Reference Include="FluentValidation, Version=6.2.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\FluentValidation.6.2.1.0\lib\portable-net40+sl50+wp80+win8+wpa81\FluentValidation.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Nancy, Version=0.23.2.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
@@ -59,6 +59,10 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Newtonsoft.Json.6.0.6\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.2.3\lib\net40\NLog.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
@@ -66,9 +70,6 @@
<Reference Include="DDay.iCal">
<HintPath>..\packages\DDay.iCal.1.0.2.575\lib\DDay.iCal.dll</HintPath>
</Reference>
<Reference Include="NLog">
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
</Reference>
<Reference Include="Omu.ValueInjecter">
<HintPath>..\packages\ValueInjecter.2.3.3\lib\net35\Omu.ValueInjecter.dll</HintPath>
</Reference>
@@ -271,7 +272,6 @@
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">

View File

@@ -93,7 +93,6 @@ namespace NzbDrone.Api
break;
case Lifetime.PerRequest:
throw new InvalidOperationException("Unable to directly register a per request lifetime.");
break;
default:
throw new ArgumentOutOfRangeException();
}
@@ -120,7 +119,6 @@ namespace NzbDrone.Api
break;
case Lifetime.PerRequest:
throw new InvalidOperationException("Unable to directly register a per request lifetime.");
break;
default:
throw new ArgumentOutOfRangeException();
}

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="DDay.iCal" version="1.0.2.575" targetFramework="net40" />
<package id="FluentValidation" version="5.5.0.0" targetFramework="net40" />
<package id="FluentValidation" version="6.2.1.0" targetFramework="net40" />
<package id="Nancy" version="0.23.2" targetFramework="net40" />
<package id="Nancy.Authentication.Basic" version="0.23.2" targetFramework="net40" />
<package id="Nancy.Authentication.Forms" version="0.23.2" targetFramework="net40" />
<package id="Newtonsoft.Json" version="6.0.6" targetFramework="net40" />
<package id="NLog" version="2.1.0" targetFramework="net40" />
<package id="NLog" version="4.2.3" targetFramework="net40" />
<package id="ValueInjecter" version="2.3.3" targetFramework="net40" />
</packages>
</packages>

View File

@@ -37,12 +37,16 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="FluentAssertions, Version=3.4.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<HintPath>..\packages\FluentAssertions.3.4.0\lib\net40\FluentAssertions.dll</HintPath>
<Reference Include="FluentAssertions, Version=4.2.1.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<HintPath>..\packages\FluentAssertions.4.2.1\lib\net40\FluentAssertions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="FluentAssertions.Core, Version=3.4.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<HintPath>..\packages\FluentAssertions.3.4.0\lib\net40\FluentAssertions.Core.dll</HintPath>
<Reference Include="FluentAssertions.Core, Version=4.2.1.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<HintPath>..\packages\FluentAssertions.4.2.1\lib\net40\FluentAssertions.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.2.3\lib\net40\NLog.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="nunit.framework, Version=2.6.3.13283, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
@@ -60,9 +64,6 @@
<Reference Include="Moq">
<HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
</Reference>
<Reference Include="NLog">
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="ContainerFixture.cs" />
@@ -104,7 +105,6 @@
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" />
<PropertyGroup>
<PostBuildEvent Condition="('$(OS)' == 'Windows_NT')">
xcopy /s /y "$(SolutionDir)\..\_output\NzbDrone.Mono.*" "$(TargetDir)"

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="FluentAssertions" version="3.4.0" targetFramework="net40" />
<package id="FluentAssertions" version="4.2.1" targetFramework="net40" />
<package id="Moq" version="4.0.10827" />
<package id="NBuilder" version="3.0.1.1" />
<package id="NLog" version="2.1.0" targetFramework="net40" />
<package id="NLog" version="4.2.3" targetFramework="net40" />
<package id="NUnit" version="2.6.3" targetFramework="net40" />
</packages>

View File

@@ -38,12 +38,16 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="FluentAssertions, Version=3.4.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<HintPath>..\packages\FluentAssertions.3.4.0\lib\net40\FluentAssertions.dll</HintPath>
<Reference Include="FluentAssertions, Version=4.2.1.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<HintPath>..\packages\FluentAssertions.4.2.1\lib\net40\FluentAssertions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="FluentAssertions.Core, Version=3.4.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<HintPath>..\packages\FluentAssertions.3.4.0\lib\net40\FluentAssertions.Core.dll</HintPath>
<Reference Include="FluentAssertions.Core, Version=4.2.1.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<HintPath>..\packages\FluentAssertions.4.2.1\lib\net40\FluentAssertions.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.2.3\lib\net40\NLog.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="nunit.framework, Version=2.6.3.13283, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
@@ -58,9 +62,6 @@
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="NLog">
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
</Reference>
<Reference Include="WebDriver, Version=2.48.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Selenium.WebDriver.2.48.0\lib\net40\WebDriver.dll</HintPath>
@@ -95,7 +96,6 @@
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="FluentAssertions" version="3.4.0" targetFramework="net40" />
<package id="NLog" version="2.1.0" targetFramework="net40" />
<package id="FluentAssertions" version="4.2.1" targetFramework="net40" />
<package id="NLog" version="4.2.3" targetFramework="net40" />
<package id="NUnit" version="2.6.3" targetFramework="net40" />
<package id="Selenium.Support" version="2.48.0" targetFramework="net40" />
<package id="Selenium.WebDriver" version="2.48.0" targetFramework="net40" />

View File

@@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using System.Threading;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Common.Cache;
namespace NzbDrone.Common.Test.CacheTests
{
[TestFixture]
public class CachedDictionaryFixture
{
private CachedDictionary<string> _cachedString;
private DictionaryWorker _worker;
[SetUp]
public void SetUp()
{
_worker = new DictionaryWorker();
_cachedString = new CachedDictionary<string>(_worker.GetDict, TimeSpan.FromMilliseconds(100));
}
[Test]
public void should_not_fetch_on_create()
{
_worker.HitCount.Should().Be(0);
}
[Test]
public void should_fetch_on_first_call()
{
var result = _cachedString.Get("Hi");
_worker.HitCount.Should().Be(1);
result.Should().Be("Value");
}
[Test]
public void should_fetch_once()
{
var result1 = _cachedString.Get("Hi");
var result2 = _cachedString.Get("HitCount");
_worker.HitCount.Should().Be(1);
}
[Test]
public void should_auto_refresh_after_lifetime()
{
var result1 = _cachedString.Get("Hi");
Thread.Sleep(200);
var result2 = _cachedString.Get("Hi");
_worker.HitCount.Should().Be(2);
}
[Test]
public void should_refresh_early_if_requested()
{
var result1 = _cachedString.Get("Hi");
Thread.Sleep(10);
_cachedString.RefreshIfExpired(TimeSpan.FromMilliseconds(1));
var result2 = _cachedString.Get("Hi");
_worker.HitCount.Should().Be(2);
}
[Test]
public void should_not_refresh_early_if_not_expired()
{
var result1 = _cachedString.Get("Hi");
_cachedString.RefreshIfExpired(TimeSpan.FromMilliseconds(50));
var result2 = _cachedString.Get("Hi");
_worker.HitCount.Should().Be(1);
}
}
public class DictionaryWorker
{
public int HitCount { get; private set; }
public Dictionary<string, string> GetDict()
{
HitCount++;
var result = new Dictionary<string, string>();
result["Hi"] = "Value";
result["HitCount"] = "Hit count is " + HitCount;
return result;
}
}
}

View File

@@ -24,6 +24,10 @@ namespace NzbDrone.Common.Test.DiskTests
{
Mocker.GetMock<IDiskProvider>(MockBehavior.Strict);
Mocker.GetMock<IDiskProvider>()
.Setup(v => v.GetMount(It.IsAny<string>()))
.Returns((IMount)null);
WithEmulatedDiskProvider();
WithExistingFile(_sourcePath);

View File

@@ -11,9 +11,11 @@ namespace NzbDrone.Common.Test.InstrumentationTests
// Indexer Urls
[TestCase(@"https://iptorrents.com/torrents/rss?u=mySecret;tp=mySecret;l5;download")]
[TestCase(@"http://rss.torrentleech.org/mySecret")]
[TestCase(@"http://rss.torrentleech.org/rss/download/12345/01233210/filename.torrent")]
[TestCase(@"http://www.bitmetv.org/rss.php?uid=mySecret&passkey=mySecret")]
[TestCase(@"https://rss.omgwtfnzbs.org/rss-search.php?catid=19,20&user=sonarr&api=mySecret&eng=1")]
[TestCase(@"https://dognzb.cr/fetch/2b51db35e1912ffc138825a12b9933d2/2b51db35e1910123321025a12b9933d2")]
[TestCase(@"https://baconbits.org/feeds.php?feed=torrents_tv&user=12345&auth=2b51db35e1910123321025a12b9933d2&passkey=mySecret&authkey=2b51db35e1910123321025a12b9933d2")]
// NzbGet
[TestCase(@"{ ""Name"" : ""ControlUsername"", ""Value"" : ""mySecret"" }, { ""Name"" : ""ControlPassword"", ""Value"" : ""mySecret"" }, ")]
[TestCase(@"{ ""Name"" : ""Server1.Username"", ""Value"" : ""mySecret"" }, { ""Name"" : ""Server1.Password"", ""Value"" : ""mySecret"" }, ")]

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -37,12 +37,16 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="FluentAssertions, Version=3.4.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<HintPath>..\packages\FluentAssertions.3.4.0\lib\net40\FluentAssertions.dll</HintPath>
<Reference Include="FluentAssertions, Version=4.2.1.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<HintPath>..\packages\FluentAssertions.4.2.1\lib\net40\FluentAssertions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="FluentAssertions.Core, Version=3.4.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<HintPath>..\packages\FluentAssertions.3.4.0\lib\net40\FluentAssertions.Core.dll</HintPath>
<Reference Include="FluentAssertions.Core, Version=4.2.1.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<HintPath>..\packages\FluentAssertions.4.2.1\lib\net40\FluentAssertions.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.2.3\lib\net40\NLog.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="nunit.framework, Version=2.6.3.13283, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
@@ -60,11 +64,9 @@
<Reference Include="Moq">
<HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
</Reference>
<Reference Include="NLog">
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="CacheTests\CachedDictionaryFixture.cs" />
<Compile Include="CacheTests\CachedFixture.cs" />
<Compile Include="CacheTests\CachedManagerFixture.cs" />
<Compile Include="ConfigFileProviderTest.cs" />
@@ -141,15 +143,14 @@
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" />
<PropertyGroup>
<PostBuildEvent Condition="'$(Configuration)|$(OS)' == 'Debug|Windows_NT'">xcopy /s /y "$(SolutionDir)\ExternalModules\CurlSharp\libs\i386\*" "$(TargetDir)"</PostBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="FluentAssertions" version="3.4.0" targetFramework="net40" />
<package id="FluentAssertions" version="4.2.1" targetFramework="net40" />
<package id="Moq" version="4.0.10827" />
<package id="NLog" version="2.1.0" targetFramework="net40" />
<package id="NLog" version="4.2.3" targetFramework="net40" />
<package id="NUnit" version="2.6.3" targetFramework="net40" />
</packages>

View File

@@ -6,8 +6,9 @@ namespace NzbDrone.Common.Cache
{
public interface ICacheManager
{
ICached<T> GetCache<T>(Type host, string name);
ICached<T> GetCache<T>(Type host);
ICached<T> GetCache<T>(Type host, string name);
ICachedDictionary<T> GetCacheDictionary<T>(Type host, string name, Func<IDictionary<string, T>> fetchFunc = null, TimeSpan? lifeTime = null);
void Clear();
ICollection<ICached> Caches { get; }
}
@@ -22,12 +23,6 @@ namespace NzbDrone.Common.Cache
}
public ICached<T> GetCache<T>(Type host)
{
Ensure.That(host, () => host).IsNotNull();
return GetCache<T>(host, host.FullName);
}
public void Clear()
{
_cache.Clear();
@@ -35,6 +30,12 @@ namespace NzbDrone.Common.Cache
public ICollection<ICached> Caches { get { return _cache.Values; } }
public ICached<T> GetCache<T>(Type host)
{
Ensure.That(host, () => host).IsNotNull();
return GetCache<T>(host, host.FullName);
}
public ICached<T> GetCache<T>(Type host, string name)
{
Ensure.That(host, () => host).IsNotNull();
@@ -42,5 +43,13 @@ namespace NzbDrone.Common.Cache
return (ICached<T>)_cache.Get(host.FullName + "_" + name, () => new Cached<T>());
}
public ICachedDictionary<T> GetCacheDictionary<T>(Type host, string name, Func<IDictionary<string, T>> fetchFunc = null, TimeSpan? lifeTime = null)
{
Ensure.That(host, () => host).IsNotNull();
Ensure.That(name, () => name).IsNotNullOrWhiteSpace();
return (ICachedDictionary<T>)_cache.Get("dict_" + host.FullName + "_" + name, () => new CachedDictionary<T>(fetchFunc, lifeTime));
}
}
}

View File

@@ -0,0 +1,137 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace NzbDrone.Common.Cache
{
public class CachedDictionary<TValue> : ICachedDictionary<TValue>
{
private readonly Func<IDictionary<string, TValue>> _fetchFunc;
private readonly TimeSpan? _ttl;
private DateTime _lastRefreshed = DateTime.MinValue;
private ConcurrentDictionary<string, TValue> _items = new ConcurrentDictionary<string, TValue>();
public CachedDictionary(Func<IDictionary<string, TValue>> fetchFunc = null, TimeSpan? ttl = null)
{
_fetchFunc = fetchFunc;
_ttl = ttl;
}
public bool IsExpired(TimeSpan ttl)
{
return _lastRefreshed.Add(ttl) < DateTime.UtcNow;
}
public void RefreshIfExpired()
{
if (_ttl.HasValue && _fetchFunc != null)
{
RefreshIfExpired(_ttl.Value);
}
}
public void RefreshIfExpired(TimeSpan ttl)
{
if (IsExpired(ttl))
{
Refresh();
}
}
public void Refresh()
{
if (_fetchFunc == null)
{
throw new InvalidOperationException("Cannot update cache without data source.");
}
Update(_fetchFunc());
ExtendTTL();
}
public void Update(IDictionary<string, TValue> items)
{
_items = new ConcurrentDictionary<string, TValue>(items);
ExtendTTL();
}
public void ExtendTTL()
{
_lastRefreshed = DateTime.UtcNow;
}
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public ICollection<TValue> Values
{
get
{
RefreshIfExpired();
return _items.Values;
}
}
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public int Count
{
get
{
RefreshIfExpired();
return _items.Count;
}
}
public TValue Get(string key)
{
RefreshIfExpired();
TValue result;
if (!_items.TryGetValue(key, out result))
{
throw new KeyNotFoundException(string.Format("Item {0} not found in cache.", key));
}
return result;
}
public TValue Find(string key)
{
RefreshIfExpired();
TValue result;
_items.TryGetValue(key, out result);
return result;
}
public void Clear()
{
_items.Clear();
_lastRefreshed = DateTime.MinValue;
}
public void ClearExpired()
{
if (!_ttl.HasValue)
{
throw new InvalidOperationException("Checking expiry without ttl not possible.");
}
if (IsExpired(_ttl.Value))
{
Clear();
}
}
public void Remove(string key)
{
TValue item;
_items.TryRemove(key, out item);
}
}
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace NzbDrone.Common.Cache
{
public interface ICachedDictionary<TValue> : ICached
{
void RefreshIfExpired();
void RefreshIfExpired(TimeSpan ttl);
void Refresh();
void Update(IDictionary<string, TValue> items);
void ExtendTTL();
TValue Get(string key);
TValue Find(string key);
bool IsExpired(TimeSpan ttl);
}
}

View File

@@ -304,7 +304,7 @@ namespace NzbDrone.Common.Disk
}
catch (Exception e)
{
Logger.WarnException(string.Format("Couldn't set permission for {0}. account:{1} rights:{2} accessControlType:{3}", filename, accountSid, rights, controlType), e);
Logger.Warn(e, string.Format("Couldn't set permission for {0}. account:{1} rights:{2} accessControlType:{3}", filename, accountSid, rights, controlType));
throw;
}
@@ -346,12 +346,12 @@ namespace NzbDrone.Common.Disk
public string[] GetFixedDrives()
{
return (DriveInfo.GetDrives().Where(x => x.DriveType == DriveType.Fixed).Select(x => x.Name)).ToArray();
return GetMounts().Where(x => x.DriveType == DriveType.Fixed).Select(x => x.RootDirectory).ToArray();
}
public string GetVolumeLabel(string path)
{
var driveInfo = DriveInfo.GetDrives().SingleOrDefault(d => d.Name == path);
var driveInfo = GetMounts().SingleOrDefault(d => d.RootDirectory.PathEquals(path));
if (driveInfo == null)
{
@@ -376,11 +376,36 @@ namespace NzbDrone.Common.Disk
return new FileStream(path, FileMode.Create);
}
public List<DriveInfo> GetDrives()
public virtual List<IMount> GetMounts()
{
return GetDriveInfoMounts();
}
public virtual IMount GetMount(string path)
{
try
{
var mounts = GetMounts();
return mounts.Where(drive => drive.RootDirectory.PathEquals(path) ||
drive.RootDirectory.IsParentPath(path))
.OrderByDescending(drive => drive.RootDirectory.Length)
.FirstOrDefault();
}
catch (Exception ex)
{
Logger.Debug(ex, string.Format("Failed to get mount for path {0}", path));
return null;
}
}
protected List<IMount> GetDriveInfoMounts()
{
return DriveInfo.GetDrives()
.Where(d => d.DriveType == DriveType.Fixed || d.DriveType == DriveType.Network)
.Where(d => d.DriveType == DriveType.Fixed || d.DriveType == DriveType.Network || d.DriveType == DriveType.Removable)
.Where(d => d.IsReady)
.Select(d => new DriveInfoMount(d))
.Cast<IMount>()
.ToList();
}
@@ -401,5 +426,19 @@ namespace NzbDrone.Common.Disk
return di.GetFiles().ToList();
}
public void RemoveEmptySubfolders(string path)
{
var subfolders = GetDirectories(path);
var files = GetFiles(path, SearchOption.AllDirectories);
foreach (var subfolder in subfolders)
{
if (files.None(f => subfolder.IsParentPath(f)))
{
DeleteFolder(subfolder, false);
}
}
}
}
}

View File

@@ -45,6 +45,13 @@ namespace NzbDrone.Common.Disk
}
public TransferMode TransferFolder(string sourcePath, string targetPath, TransferMode mode, bool verified = true)
{
var verificationMode = verified ? VerificationMode : DiskTransferVerificationMode.VerifyOnly;
return TransferFolder(sourcePath, targetPath, mode, verificationMode);
}
public TransferMode TransferFolder(string sourcePath, string targetPath, TransferMode mode, DiskTransferVerificationMode verificationMode)
{
Ensure.That(sourcePath, () => sourcePath).IsValidPath();
Ensure.That(targetPath, () => targetPath).IsValidPath();
@@ -58,14 +65,14 @@ namespace NzbDrone.Common.Disk
foreach (var subDir in _diskProvider.GetDirectoryInfos(sourcePath))
{
result &= TransferFolder(subDir.FullName, Path.Combine(targetPath, subDir.Name), mode, verified);
result &= TransferFolder(subDir.FullName, Path.Combine(targetPath, subDir.Name), mode, verificationMode);
}
foreach (var sourceFile in _diskProvider.GetFileInfos(sourcePath))
{
var destFile = Path.Combine(targetPath, sourceFile.Name);
result &= TransferFile(sourceFile.FullName, destFile, mode, true, verified);
result &= TransferFile(sourceFile.FullName, destFile, mode, true, verificationMode);
}
if (mode.HasFlag(TransferMode.Move))
@@ -77,15 +84,17 @@ namespace NzbDrone.Common.Disk
}
public TransferMode TransferFile(string sourcePath, string targetPath, TransferMode mode, bool overwrite = false, bool verified = true)
{
var verificationMode = verified ? VerificationMode : DiskTransferVerificationMode.None;
return TransferFile(sourcePath, targetPath, mode, overwrite, verificationMode);
}
public TransferMode TransferFile(string sourcePath, string targetPath, TransferMode mode, bool overwrite, DiskTransferVerificationMode verificationMode)
{
Ensure.That(sourcePath, () => sourcePath).IsValidPath();
Ensure.That(targetPath, () => targetPath).IsValidPath();
if (VerificationMode != DiskTransferVerificationMode.Transactional && VerificationMode != DiskTransferVerificationMode.TryTransactional)
{
verified = false;
}
_logger.Debug("{0} [{1}] > [{2}]", mode, sourcePath, targetPath);
var originalSize = _diskProvider.GetFileSize(sourcePath);
@@ -154,49 +163,59 @@ namespace NzbDrone.Common.Disk
}
}
if (verified)
// We force a transactional transfer if the transfer occurs between mounts and one of the mounts is cifs, it would be a copy anyway.
if (verificationMode == DiskTransferVerificationMode.TryTransactional && OsInfo.IsNotWindows)
{
if (mode.HasFlag(TransferMode.Copy))
var sourceMount = _diskProvider.GetMount(sourcePath);
var targetMount = _diskProvider.GetMount(targetPath);
if (sourceMount != null && targetMount != null && sourceMount.RootDirectory != targetMount.RootDirectory &&
(sourceMount.DriveFormat == "cifs" || targetMount.DriveFormat == "cifs"))
{
verificationMode = DiskTransferVerificationMode.Transactional;
}
}
if (mode.HasFlag(TransferMode.Copy))
{
if (verificationMode == DiskTransferVerificationMode.Transactional || verificationMode == DiskTransferVerificationMode.TryTransactional)
{
if (TryCopyFileTransactional(sourcePath, targetPath, originalSize))
{
return TransferMode.Copy;
}
}
if (mode.HasFlag(TransferMode.Move))
{
if (TryMoveFileTransactional(sourcePath, targetPath, originalSize))
{
return TransferMode.Move;
}
throw new IOException(string.Format("Failed to completely transfer [{0}] to [{1}], aborting.", sourcePath, targetPath));
}
throw new IOException(string.Format("Failed to completely transfer [{0}] to [{1}], aborting.", sourcePath, targetPath));
}
else if (VerificationMode != DiskTransferVerificationMode.None)
{
if (mode.HasFlag(TransferMode.Copy))
else if (verificationMode == DiskTransferVerificationMode.VerifyOnly)
{
TryCopyFileVerified(sourcePath, targetPath, originalSize);
return TransferMode.Copy;
}
if (mode.HasFlag(TransferMode.Move))
{
TryMoveFileVerified(sourcePath, targetPath, originalSize);
return TransferMode.Move;
}
}
else
{
if (mode.HasFlag(TransferMode.Copy))
else
{
_diskProvider.CopyFile(sourcePath, targetPath);
return TransferMode.Copy;
}
}
if (mode.HasFlag(TransferMode.Move))
if (mode.HasFlag(TransferMode.Move))
{
if (verificationMode == DiskTransferVerificationMode.Transactional || verificationMode == DiskTransferVerificationMode.TryTransactional)
{
if (TryMoveFileTransactional(sourcePath, targetPath, originalSize, verificationMode))
{
return TransferMode.Move;
}
throw new IOException(string.Format("Failed to completely transfer [{0}] to [{1}], aborting.", sourcePath, targetPath));
}
else if (verificationMode == DiskTransferVerificationMode.VerifyOnly)
{
TryMoveFileVerified(sourcePath, targetPath, originalSize);
return TransferMode.Move;
}
else
{
_diskProvider.MoveFile(sourcePath, targetPath);
return TransferMode.Move;
@@ -240,7 +259,7 @@ namespace NzbDrone.Common.Disk
}
catch (Exception ex)
{
_logger.ErrorException(string.Format("Failed to properly rollback the file move [{0}] to [{1}], incomplete file may be left in target path.", sourcePath, targetPath), ex);
_logger.Error(ex, string.Format("Failed to properly rollback the file move [{0}] to [{1}], incomplete file may be left in target path.", sourcePath, targetPath));
}
}
@@ -256,7 +275,7 @@ namespace NzbDrone.Common.Disk
}
catch (Exception ex)
{
_logger.ErrorException(string.Format("Failed to properly rollback the file move [{0}] to [{1}], file may be left in target path.", sourcePath, targetPath), ex);
_logger.Error(ex, string.Format("Failed to properly rollback the file move [{0}] to [{1}], file may be left in target path.", sourcePath, targetPath));
}
}
@@ -275,7 +294,7 @@ namespace NzbDrone.Common.Disk
}
catch (Exception ex)
{
_logger.ErrorException(string.Format("Failed to properly rollback the file copy [{0}] to [{1}], file may be left in target path.", sourcePath, targetPath), ex);
_logger.Error(ex, string.Format("Failed to properly rollback the file copy [{0}] to [{1}], file may be left in target path.", sourcePath, targetPath));
}
}
@@ -340,7 +359,7 @@ namespace NzbDrone.Common.Disk
return false;
}
private bool TryMoveFileTransactional(string sourcePath, string targetPath, long originalSize)
private bool TryMoveFileTransactional(string sourcePath, string targetPath, long originalSize, DiskTransferVerificationMode verificationMode)
{
var backupPath = sourcePath + ".backup~";
var tempTargetPath = targetPath + ".partial~";
@@ -394,7 +413,7 @@ namespace NzbDrone.Common.Disk
}
}
if (VerificationMode == DiskTransferVerificationMode.Transactional)
if (verificationMode == DiskTransferVerificationMode.Transactional)
{
_logger.Trace("Hardlink move failed, reverting to copy.");
if (TryCopyFileTransactional(sourcePath, targetPath, originalSize))

View File

@@ -0,0 +1,76 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using NzbDrone.Common.Extensions;
namespace NzbDrone.Common.Disk
{
public class DriveInfoMount : IMount
{
private readonly DriveInfo _driveInfo;
public DriveInfoMount(DriveInfo driveInfo)
{
_driveInfo = driveInfo;
}
public long AvailableFreeSpace
{
get { return _driveInfo.AvailableFreeSpace; }
}
public string DriveFormat
{
get { return _driveInfo.DriveFormat; }
}
public DriveType DriveType
{
get { return _driveInfo.DriveType; }
}
public bool IsReady
{
get { return _driveInfo.IsReady; }
}
public string Name
{
get { return _driveInfo.Name; }
}
public string RootDirectory
{
get { return _driveInfo.RootDirectory.FullName; }
}
public long TotalFreeSpace
{
get { return _driveInfo.TotalFreeSpace; }
}
public long TotalSize
{
get { return _driveInfo.TotalSize; }
}
public string VolumeLabel
{
get { return _driveInfo.VolumeLabel; }
}
public string VolumeName
{
get
{
if (VolumeLabel.IsNullOrWhiteSpace())
{
return Name;
}
return string.Format("{0} ({1})", Name, VolumeLabel);
}
}
}
}

View File

@@ -103,12 +103,12 @@ namespace NzbDrone.Common.Disk
private List<FileSystemModel> GetDrives()
{
return _diskProvider.GetDrives()
return _diskProvider.GetMounts()
.Select(d => new FileSystemModel
{
Type = FileSystemEntityType.Drive,
Name = GetVolumeName(d),
Path = d.Name,
Name = d.VolumeLabel,
Path = d.RootDirectory,
LastModified = null
})
.ToList();
@@ -157,16 +157,6 @@ namespace NzbDrone.Common.Disk
return path;
}
private string GetVolumeName(DriveInfo driveInfo)
{
if (driveInfo.VolumeLabel.IsNullOrWhiteSpace())
{
return driveInfo.Name;
}
return string.Format("{0} ({1})", driveInfo.Name, driveInfo.VolumeLabel);
}
private string GetParent(string path)
{

View File

@@ -40,12 +40,13 @@ namespace NzbDrone.Common.Disk
void SetPermissions(string filename, WellKnownSidType accountSid, FileSystemRights rights, AccessControlType controlType);
FileAttributes GetFileAttributes(string path);
void EmptyFolder(string path);
string[] GetFixedDrives();
string GetVolumeLabel(string path);
FileStream OpenReadStream(string path);
FileStream OpenWriteStream(string path);
List<DriveInfo> GetDrives();
List<IMount> GetMounts();
IMount GetMount(string path);
List<DirectoryInfo> GetDirectoryInfos(string path);
List<FileInfo> GetFileInfos(string path);
void RemoveEmptySubfolders(string path);
}
}

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace NzbDrone.Common.Disk
{
public interface IMount
{
long AvailableFreeSpace { get; }
string DriveFormat { get; }
DriveType DriveType { get; }
bool IsReady { get; }
string Name { get; }
string RootDirectory { get; }
long TotalFreeSpace { get; }
long TotalSize { get; }
string VolumeLabel { get; }
}
}

View File

@@ -43,7 +43,7 @@ namespace NzbDrone.Common.EnvironmentInfo
}
catch (Exception ex)
{
_logger.WarnException("Coudn't set app folder permission", ex);
_logger.Warn(ex, "Coudn't set app folder permission");
}
}
}

View File

@@ -60,7 +60,7 @@ namespace NzbDrone.Common.EnvironmentInfo
}
catch (Exception ex)
{
_logger.WarnException("Error checking if the current user is an administrator.", ex);
_logger.Warn(ex, "Error checking if the current user is an administrator.");
return false;
}
}

View File

@@ -73,8 +73,14 @@ namespace NzbDrone.Common.Extensions
public static bool IsParentPath(this string parentPath, string childPath)
{
parentPath = parentPath.TrimEnd(Path.DirectorySeparatorChar);
childPath = childPath.TrimEnd(Path.DirectorySeparatorChar);
if (parentPath != "/")
{
parentPath = parentPath.TrimEnd(Path.DirectorySeparatorChar);
}
if (childPath != "/")
{
childPath = childPath.TrimEnd(Path.DirectorySeparatorChar);
}
var parent = new DirectoryInfo(parentPath);
var child = new DirectoryInfo(childPath);

View File

@@ -29,7 +29,7 @@ namespace NzbDrone.Common.Http.Dispatchers
}
catch (Exception ex)
{
_logger.TraceException("Initializing curl failed", ex);
_logger.Trace(ex, "Initializing curl failed");
return false;
}
}
@@ -112,7 +112,15 @@ namespace NzbDrone.Common.Http.Dispatchers
if (result != CurlCode.Ok)
{
throw new WebException(string.Format("Curl Error {0} for Url {1}", result, curlEasy.Url));
switch (result)
{
case CurlCode.SslCaCert:
case (CurlCode)77:
throw new WebException(string.Format("Curl Error {0} for Url {1}, issues with your operating system SSL Root Certificate Bundle (ca-bundle).", result, curlEasy.Url));
default:
throw new WebException(string.Format("Curl Error {0} for Url {1}", result, curlEasy.Url));
}
}
}

View File

@@ -100,7 +100,6 @@ namespace NzbDrone.Common.Http.Dispatchers
break;
case "Range":
throw new NotImplementedException();
break;
case "Referer":
webRequest.Referer = header.Value.ToString();
break;
@@ -111,7 +110,6 @@ namespace NzbDrone.Common.Http.Dispatchers
throw new NotSupportedException("User-Agent other than Sonarr not allowed.");
case "Proxy-Connection":
throw new NotImplementedException();
break;
default:
webRequest.Headers.Add(header.Key, header.Value.ToString());
break;

View File

@@ -28,7 +28,6 @@ namespace NzbDrone.Common.Http
private readonly Logger _logger;
private readonly IRateLimitService _rateLimitService;
private readonly ICached<CookieContainer> _cookieContainerCache;
private readonly ICached<bool> _curlTLSFallbackCache;
private readonly List<IHttpRequestInterceptor> _requestInterceptors;
private readonly IHttpDispatcher _httpDispatcher;
@@ -177,7 +176,7 @@ namespace NzbDrone.Common.Http
}
catch (Exception e)
{
_logger.WarnException("Failed to get response from: " + url, e);
_logger.Warn(e, "Failed to get response from: " + url);
throw;
}
}

View File

@@ -53,7 +53,7 @@ namespace NzbDrone.Common.Http
}
catch (Exception e)
{
_logger.WarnException("Failed to get response from: " + url, e);
_logger.Warn(e, "Failed to get response from: " + url);
throw;
}
}

View File

@@ -9,9 +9,10 @@ namespace NzbDrone.Common.Instrumentation
private static readonly Regex[] CleansingRules = new[]
{
// Url
new Regex(@"(?<=\?|&)(apikey|token|passkey|uid|api)=(?<secret>[^&=]+?)(?= |&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
new Regex(@"(?<=\?|&)(apikey|token|passkey|auth|authkey|user|uid|api)=(?<secret>[^&=]+?)(?= |&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
new Regex(@"(?<=\?|&)[^=]*?(username|password)=(?<secret>[^&=]+?)(?= |&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
new Regex(@"torrentleech\.org/(?<secret>[0-9a-z]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
new Regex(@"torrentleech\.org/(?!rss)(?<secret>[0-9a-z]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
new Regex(@"torrentleech\.org/rss/download/[0-9]+/(?<secret>[0-9a-z]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
new Regex(@"iptorrents\.com/[/a-z0-9?&;]*?(?:[?&;](u|tp)=(?<secret>[^&=;]+?))+(?= |;|&|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
new Regex(@"/fetch/[a-z0-9]{32}/(?<secret>[a-z0-9]{32})", RegexOptions.Compiled),
@@ -49,7 +50,7 @@ namespace NzbDrone.Common.Instrumentation
var value = m.Value;
foreach (var capture in m.Groups["secret"].Captures.OfType<Capture>().Reverse())
{
value = value.Replace(capture.Index - m.Index, capture.Length, "<removed>");
value = value.Replace(capture.Index - m.Index, capture.Length, "(removed)");
}
return value;

View File

@@ -19,7 +19,7 @@ namespace NzbDrone.Common.Instrumentation
var exception = e.Exception;
Console.WriteLine("Task Error: {0}", exception);
Logger.Error("Task Error: " + exception.Message, exception);
Logger.Error(exception, "Task Error: " + exception.Message);
}
private static void HandleAppDomainException(object sender, UnhandledExceptionEventArgs e)
@@ -40,13 +40,13 @@ namespace NzbDrone.Common.Instrumentation
if (exception is TypeInitializationException && exception.InnerException is DllNotFoundException ||
exception is DllNotFoundException)
{
Logger.DebugException("Minor Fail: " + exception.Message, exception);
Logger.Debug(exception, "Minor Fail: " + exception.Message);
return;
}
}
Console.WriteLine("EPIC FAIL: {0}", exception);
Logger.FatalException("EPIC FAIL: " + exception.Message, exception);
Logger.Fatal(exception, "EPIC FAIL: " + exception.Message);
}
}
}

View File

@@ -76,7 +76,7 @@ namespace NzbDrone.Common.Instrumentation
{
DebuggerTarget target = new DebuggerTarget();
target.Name = "debuggerLogger";
target.Layout = "[${level}] [${threadid}] ${logger}: ${message} ${onexception:inner=${newline}${newline}${exception:format=ToString}${newline}}";
target.Layout = "[${level}] [${threadid}] ${logger}: ${message} ${onexception:inner=${newline}${newline}[v${assembly-version}] ${exception:format=ToString}${newline}}";
var loggingRule = new LoggingRule("*", LogLevel.Trace, target);
LogManager.Configuration.AddTarget("debugger", target);
@@ -91,7 +91,7 @@ namespace NzbDrone.Common.Instrumentation
var coloredConsoleTarget = new ColoredConsoleTarget();
coloredConsoleTarget.Name = "consoleLogger";
coloredConsoleTarget.Layout = "[${level}] ${logger}: ${message} ${onexception:inner=${newline}${newline}${exception:format=ToString}${newline}}";
coloredConsoleTarget.Layout = "[${level}] ${logger}: ${message} ${onexception:inner=${newline}${newline}[v${assembly-version}] ${exception:format=ToString}${newline}}";
var loggingRule = new LoggingRule("*", level, coloredConsoleTarget);
@@ -99,29 +99,38 @@ namespace NzbDrone.Common.Instrumentation
LogManager.Configuration.LoggingRules.Add(loggingRule);
}
const string FILE_LOG_LAYOUT = @"${date:format=yy-M-d HH\:mm\:ss.f}|${level}|${logger}|${message}${onexception:inner=${newline}${newline}${exception:format=ToString}${newline}}";
const string FILE_LOG_LAYOUT = @"${date:format=yy-M-d HH\:mm\:ss.f}|${level}|${logger}|${message}${onexception:inner=${newline}${newline}[v${assembly-version}] ${exception:format=ToString}${newline}}";
private static void RegisterAppFile(IAppFolderInfo appFolderInfo)
{
RegisterAppFile(appFolderInfo, "appFileInfo", "sonarr.txt", 5);
RegisterAppFile(appFolderInfo, "appFileDebug", "sonarr.debug.txt", 50);
RegisterAppFile(appFolderInfo, "appFileTrace", "sonarr.trace.txt", 50);
}
private static LoggingRule RegisterAppFile(IAppFolderInfo appFolderInfo, string name, string fileName, int maxArchiveFiles)
{
var fileTarget = new NzbDroneFileTarget();
fileTarget.Name = "rollingFileLogger";
fileTarget.FileName = Path.Combine(appFolderInfo.GetLogFolder(), "nzbdrone.txt");
fileTarget.Name = name;
fileTarget.FileName = Path.Combine(appFolderInfo.GetLogFolder(), fileName);
fileTarget.AutoFlush = true;
fileTarget.KeepFileOpen = false;
fileTarget.ConcurrentWrites = false;
fileTarget.ConcurrentWriteAttemptDelay = 50;
fileTarget.ConcurrentWriteAttempts = 10;
fileTarget.ArchiveAboveSize = 1024000;
fileTarget.MaxArchiveFiles = 5;
fileTarget.MaxArchiveFiles = maxArchiveFiles;
fileTarget.EnableFileDelete = true;
fileTarget.ArchiveNumbering = ArchiveNumberingMode.Rolling;
fileTarget.Layout = FILE_LOG_LAYOUT;
var loggingRule = new LoggingRule("*", LogLevel.Trace, fileTarget);
LogManager.Configuration.AddTarget("appfile", fileTarget);
LogManager.Configuration.AddTarget(name, fileTarget);
LogManager.Configuration.LoggingRules.Add(loggingRule);
return loggingRule;
}
private static void RegisterUpdateFile(IAppFolderInfo appFolderInfo)

View File

@@ -43,6 +43,10 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Newtonsoft.Json.6.0.6\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.2.3\lib\net40\NLog.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Configuration.Install" />
@@ -51,10 +55,7 @@
<Reference Include="System.ServiceProcess" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="ICSharpCode.SharpZipLib">
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
</Reference>
<Reference Include="NLog">
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
<HintPath>..\packages\ICSharpCode.SharpZipLib.Patched.0.86.5\lib\net20\ICSharpCode.SharpZipLib.dll</HintPath>
</Reference>
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
@@ -63,7 +64,9 @@
<Compile Include="ArchiveService.cs" />
<Compile Include="Cache\Cached.cs" />
<Compile Include="Cache\CacheManager.cs" />
<Compile Include="Cache\CachedDictionary.cs" />
<Compile Include="Cache\ICached.cs" />
<Compile Include="Cache\ICachedDictionary.cs" />
<Compile Include="Cloud\CloudClient.cs" />
<Compile Include="Composition\Container.cs" />
<Compile Include="Composition\ContainerBuilderBase.cs" />
@@ -72,6 +75,8 @@
<Compile Include="ConvertBase32.cs" />
<Compile Include="Crypto\HashProvider.cs" />
<Compile Include="Disk\FileSystemLookupService.cs" />
<Compile Include="Disk\DriveInfoMount.cs" />
<Compile Include="Disk\IMount.cs" />
<Compile Include="Disk\RelativeFileSystemModel.cs" />
<Compile Include="Disk\FileSystemModel.cs" />
<Compile Include="Disk\FileSystemResult.cs" />
@@ -229,7 +234,6 @@
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">

View File

@@ -37,7 +37,7 @@ namespace NzbDrone.Common.Processes
}
catch (Exception ex)
{
_logger.Error("Unable to write PID file: " + filename, ex);
_logger.Error(ex, "Unable to write PID file: " + filename);
throw;
}
}

View File

@@ -292,7 +292,7 @@ namespace NzbDrone.Common.Processes
}
catch (Win32Exception e)
{
_logger.WarnException("Couldn't get process info for " + process.ProcessName, e);
_logger.Warn(e, "Couldn't get process info for " + process.ProcessName);
}
return processInfo;

View File

@@ -17,7 +17,7 @@ namespace NzbDrone.Common.TPL
var aggregateException = t.Exception.Flatten();
foreach (var exception in aggregateException.InnerExceptions)
{
Logger.ErrorException("Task Error", exception);
Logger.Error(exception, "Task Error");
}
}
}, TaskContinuationOptions.OnlyOnFaulted);

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="ICSharpCode.SharpZipLib.Patched" version="0.86.5" targetFramework="net40" />
<package id="Newtonsoft.Json" version="6.0.6" targetFramework="net40" />
<package id="NLog" version="2.1.0" targetFramework="net40" />
<package id="SharpZipLib" version="0.86.0" targetFramework="net40" />
<package id="NLog" version="4.2.3" targetFramework="net40" />
</packages>

View File

@@ -32,7 +32,7 @@ namespace NzbDrone.Console
{
System.Console.WriteLine("");
System.Console.WriteLine("");
Logger.FatalException("EPIC FAIL!", e);
Logger.Fatal(e, "EPIC FAIL!");
System.Console.WriteLine("Press any key to exit...");
System.Console.ReadLine();
Environment.Exit(1);

View File

@@ -75,11 +75,12 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Newtonsoft.Json.6.0.6\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.2.3\lib\net40\NLog.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="NLog">
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
</Reference>
<Reference Include="Owin">
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
</Reference>
@@ -143,7 +144,6 @@
<PreBuildEvent>
</PreBuildEvent>
</PropertyGroup>
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">

View File

@@ -3,6 +3,6 @@
<package id="Microsoft.Owin" version="2.1.0" targetFramework="net40" />
<package id="Microsoft.Owin.Hosting" version="2.1.0" targetFramework="net40" />
<package id="Newtonsoft.Json" version="6.0.6" targetFramework="net40" />
<package id="NLog" version="2.1.0" targetFramework="net40" />
<package id="NLog" version="4.2.3" targetFramework="net40" />
<package id="Owin" version="1.0" targetFramework="net40" />
</packages>
</packages>

View File

@@ -124,7 +124,7 @@ namespace NzbDrone.Core.Test.DataAugmentation.Scene
.Returns(Builder<SceneMapping>.CreateListOfSize(1).Build());
Subject.HandleAsync(new ApplicationStartedEvent());
Subject.Execute(new UpdateSceneMappingCommand());
Mocker.GetMock<ISceneMappingRepository>()
.Verify(v => v.All(), Times.Once());

View File

@@ -11,6 +11,7 @@ using NzbDrone.Core.DataAugmentation.Xem.Model;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Tv.Events;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.DataAugmentation.SceneNumbering
{
@@ -144,6 +145,25 @@ namespace NzbDrone.Core.Test.DataAugmentation.SceneNumbering
Mocker.GetMock<ISeriesService>()
.Verify(v => v.UpdateSeries(It.IsAny<Series>()), Times.Never());
ExceptionVerification.ExpectedWarns(1);
}
[Test]
public void should_not_clear_scenenumbering_if_thexem_throws()
{
GivenExistingMapping();
Mocker.GetMock<IXemProxy>()
.Setup(v => v.GetXemSeriesIds())
.Throws(new InvalidOperationException());
Subject.Handle(new SeriesUpdatedEvent(_series));
Mocker.GetMock<ISeriesService>()
.Verify(v => v.UpdateSeries(It.IsAny<Series>()), Times.Never());
ExceptionVerification.ExpectedWarns(1);
}
[Test]

View File

@@ -2,11 +2,7 @@
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Datastore.Migration;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Profiles.Delay;
using NzbDrone.Core.Tags;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Test.Datastore.Migration
{
@@ -16,7 +12,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
[Test]
public void should_migrate_old_delays()
{
WithTestDb(c =>
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Profiles").Row(new
{
@@ -35,10 +31,10 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var allProfiles = Mocker.Resolve<DelayProfileRepository>().All().ToList();
var allProfiles = db.Query<DelayProfile70>("SELECT * FROM DelayProfiles");
allProfiles.Should().HaveCount(3);
allProfiles.Should().OnlyContain(c => c.PreferredProtocol == DownloadProtocol.Usenet);
allProfiles.Should().OnlyContain(c => c.PreferredProtocol == 1);
allProfiles.Should().OnlyContain(c => c.TorrentDelay == 0);
allProfiles.Should().Contain(c => c.UsenetDelay == 60);
allProfiles.Should().Contain(c => c.UsenetDelay == 120);
@@ -47,17 +43,18 @@ namespace NzbDrone.Core.Test.Datastore.Migration
[Test]
public void should_create_tag_for_delay_profile()
{
WithTestDb(c =>
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Profiles").Row(new
{
GrabDelay = 1,
Name = "OneHour",
Cutoff = 0,
Items = "[]"
})
);
});
});
var tags = Mocker.Resolve<TagRepository>().All().ToList();
var tags = db.Query<Tag69>("SELECT * FROM Tags");
tags.Should().HaveCount(1);
tags.First().Label.Should().Be("delay-60");
@@ -66,7 +63,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
[Test]
public void should_add_tag_to_series_that_had_a_profile_with_delay_attached()
{
WithTestDb(c =>
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Profiles").Row(new
{
@@ -95,12 +92,11 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var tag = Mocker.Resolve<TagRepository>().All().ToList().First();
var series = Mocker.Resolve<SeriesRepository>().All().ToList();
var tag = db.Query<Tag69>("SELECT Id, Label FROM Tags").Single();
var series = db.Query<Series69>("SELECT Tags FROM Series");
series.Should().HaveCount(1);
series.First().Tags.Should().HaveCount(1);
series.First().Tags.First().Should().Be(tag.Id);
series.First().Tags.Should().BeEquivalentTo(tag.Id);
}
}
}

View File

@@ -2,12 +2,7 @@
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Datastore.Migration;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Profiles;
using NzbDrone.Core.Profiles.Delay;
using NzbDrone.Core.Tags;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Test.Datastore.Migration
{
@@ -17,10 +12,11 @@ namespace NzbDrone.Core.Test.Datastore.Migration
[Test]
public void should_add_unknown_to_old_profile()
{
WithTestDb(c =>
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Profiles").Row(new
{
Id = 0,
Name = "SDTV",
Cutoff = 1,
Items = "[ { \"quality\": 1, \"allowed\": true } ]",
@@ -28,11 +24,12 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var allProfiles = Mocker.Resolve<ProfileRepository>().All().ToList();
var profiles = db.Query<Profile70>("SELECT Items FROM Profiles LIMIT 1");
allProfiles.Should().HaveCount(1);
allProfiles.First().Items.Should().HaveCount(2);
allProfiles.First().Items.Should().Contain(i => i.Quality.Id == 0 && i.Allowed == false);
var items = profiles.First().Items;
items.Should().HaveCount(2);
items.First().Quality.Should().Be(0);
items.First().Allowed.Should().Be(false);
}
}
}

View File

@@ -6,7 +6,6 @@ using FluentMigrator;
using NUnit.Framework;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Datastore.Migration;
using NzbDrone.Core.History;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Datastore.Migration
@@ -17,7 +16,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
[Test]
public void should_move_grab_id_from_date_to_columns()
{
WithTestDb(c =>
var db = WithMigrationTestDb(c =>
{
InsertHistory(c, new Dictionary<string, string>
{
@@ -33,19 +32,19 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
var allProfiles = Mocker.Resolve<HistoryRepository>().All().ToList();
var history = db.Query<History72>("SELECT DownloadId, Data FROM History");
allProfiles.Should().HaveCount(2);
allProfiles.Should().NotContain(c => c.Data.ContainsKey("downloadClientId"));
allProfiles.Should().Contain(c => c.DownloadId == "123");
allProfiles.Should().Contain(c => c.DownloadId == "abc");
history.Should().HaveCount(2);
history.Should().NotContain(c => c.Data.ContainsKey("downloadClientId"));
history.Should().Contain(c => c.DownloadId == "123");
history.Should().Contain(c => c.DownloadId == "abc");
}
[Test]
public void should_leave_items_with_no_grabid()
{
WithTestDb(c =>
var db = WithMigrationTestDb(c =>
{
InsertHistory(c, new Dictionary<string, string>
{
@@ -60,18 +59,18 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
var allProfiles = Mocker.Resolve<HistoryRepository>().All().ToList();
var history = db.Query<History72>("SELECT DownloadId, Data FROM History");
allProfiles.Should().HaveCount(2);
allProfiles.Should().NotContain(c => c.Data.ContainsKey("downloadClientId"));
allProfiles.Should().Contain(c => c.DownloadId == "123");
allProfiles.Should().Contain(c => c.DownloadId == null);
history.Should().HaveCount(2);
history.Should().NotContain(c => c.Data.ContainsKey("downloadClientId"));
history.Should().Contain(c => c.DownloadId == "123");
history.Should().Contain(c => c.DownloadId == null);
}
[Test]
public void should_leave_other_data()
{
WithTestDb(c =>
var db = WithMigrationTestDb(c =>
{
InsertHistory(c, new Dictionary<string, string>
{
@@ -81,16 +80,15 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var allProfiles = Mocker.Resolve<HistoryRepository>().All().Single();
var history = db.Query<History72>("SELECT DownloadId, Data FROM History").Single();
allProfiles.Data.Should().NotContainKey("downloadClientId");
allProfiles.Data.Should().Contain(new KeyValuePair<string, string>("indexer", "test"));
allProfiles.Data.Should().Contain(new KeyValuePair<string, string>("group", "test2"));
history.Data.Should().NotContainKey("downloadClientId");
history.Data.Should().Contain(new KeyValuePair<string, string>("indexer", "test"));
history.Data.Should().Contain(new KeyValuePair<string, string>("group", "test2"));
allProfiles.DownloadId.Should().Be("123");
history.DownloadId.Should().Be("123");
}
private void InsertHistory(MigrationBase migrationBase, Dictionary<string, string> data)
{
migrationBase.Insert.IntoTable("History").Row(new

View File

@@ -1,29 +1,28 @@
using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Jobs;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Datastore.Migration;
namespace NzbDrone.Core.Test.Datastore.Migration
{
[TestFixture]
public class force_lib_updateFixture : MigrationTest<Core.Datastore.Migration.force_lib_update>
public class force_lib_updateFixture : MigrationTest<force_lib_update>
{
[Test]
public void should_not_fail_on_empty_db()
{
WithTestDb(c => { });
var db = WithMigrationTestDb();
Mocker.Resolve<ScheduledTaskRepository>().All().Should().BeEmpty();
Mocker.Resolve<SeriesRepository>().All().Should().BeEmpty();
db.Query("SELECT * FROM ScheduledTasks").Should().BeEmpty();
db.Query("SELECT * FROM Series").Should().BeEmpty();
}
[Test]
public void should_reset_job_last_execution_time()
{
WithTestDb(c =>
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("ScheduledTasks").Row(new
{
@@ -40,7 +39,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var jobs = Mocker.Resolve<ScheduledTaskRepository>().All().ToList();
var jobs = db.Query<ScheduledTasks75>("SELECT TypeName, LastExecution FROM ScheduledTasks");
jobs.Single(c => c.TypeName == "NzbDrone.Core.Tv.Commands.RefreshSeriesCommand")
.LastExecution.Year.Should()
@@ -51,11 +50,10 @@ namespace NzbDrone.Core.Test.Datastore.Migration
.Be(2000);
}
[Test]
public void should_reset_series_last_sync_time()
{
WithTestDb(c =>
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Series").Row(new
{
@@ -92,9 +90,9 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var jobs = Mocker.Resolve<SeriesRepository>().All().ToList();
var series = db.Query<Series69>("SELECT LastInfoSync FROM Series");
jobs.Should().OnlyContain(c => c.LastInfoSync.Value.Year == 2014);
series.Should().OnlyContain(c => c.LastInfoSync.Value.Year == 2014);
}
}
}

View File

@@ -1,21 +1,18 @@
using System;
using System.Linq;
using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Jobs;
using NzbDrone.Core.Tags;
using NzbDrone.Core.Datastore.Migration;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Test.Datastore.Migration
{
[TestFixture]
public class dedupe_tagsFixture : MigrationTest<Core.Datastore.Migration.dedupe_tags>
public class dedupe_tagsFixture : MigrationTest<dedupe_tags>
{
[Test]
public void should_not_fail_if_series_tags_are_null()
{
WithTestDb(c =>
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Series").Row(new
{
@@ -40,13 +37,14 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
Mocker.Resolve<TagRepository>().All().Should().HaveCount(1);
var tags = db.Query<Tag69>("SELECT * FROM Tags");
tags.Should().HaveCount(1);
}
[Test]
public void should_not_fail_if_series_tags_are_empty()
{
WithTestDb(c =>
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Series").Row(new
{
@@ -72,13 +70,14 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
Mocker.Resolve<TagRepository>().All().Should().HaveCount(1);
var tags = db.Query<Tag69>("SELECT * FROM Tags");
tags.Should().HaveCount(1);
}
[Test]
public void should_remove_duplicate_labels_from_tags()
{
WithTestDb(c =>
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Tags").Row(new
{
@@ -91,13 +90,14 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
Mocker.Resolve<TagRepository>().All().Should().HaveCount(1);
var tags = db.Query<Tag69>("SELECT * FROM Tags");
tags.Should().HaveCount(1);
}
[Test]
public void should_not_allow_duplicate_tag_to_be_inserted()
{
WithTestDb(c =>
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Tags").Row(new
{
@@ -105,13 +105,13 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
Assert.That(() => Mocker.Resolve<TagRepository>().Insert(new Tag { Label = "test" }), Throws.Exception);
Assert.That(() => db.Query("INSERT INTO Tags (Label) VALUES ('test')"), Throws.Exception);
}
[Test]
public void should_replace_duplicated_tag_with_proper_tag()
{
WithTestDb(c =>
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Series").Row(new
{
@@ -142,13 +142,14 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
Mocker.Resolve<SeriesRepository>().Get(1).Tags.First().Should().Be(1);
var series = db.Query<Series69>("SELECT Tags FROM Series WHERE Id = 1").Single();
series.Tags.First().Should().Be(1);
}
[Test]
public void should_only_update_affected_series()
{
WithTestDb(c =>
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Series").Row(new
{
@@ -197,7 +198,8 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
Mocker.Resolve<SeriesRepository>().Get(2).Tags.Should().BeEmpty();
var series = db.Query<Series69>("SELECT Tags FROM Series WHERE Id = 2").Single();
series.Tags.Should().BeEmpty();
}
}
}

View File

@@ -3,27 +3,25 @@ using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Download;
using NzbDrone.Core.Download.Clients.Sabnzbd;
using NzbDrone.Core.Download.Clients.Transmission;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Datastore.Migration;
namespace NzbDrone.Core.Test.Datastore.Migration
{
[TestFixture]
public class move_dot_prefix_to_transmission_categoryFixture : MigrationTest<Core.Datastore.Migration.move_dot_prefix_to_transmission_category>
public class move_dot_prefix_to_transmission_categoryFixture : MigrationTest<move_dot_prefix_to_transmission_category>
{
[Test]
public void should_not_fail_if_no_transmission()
{
WithTestDb(c =>
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("DownloadClients").Row(new
c.Insert.IntoTable("DownloadClients").Row(new
{
Enable = 1,
Name = "Sab",
Implementation = "Sabnzbd",
Settings = new SabnzbdSettings
Settings = new
{
Host = "127.0.0.1",
TvCategory = "abc"
@@ -32,24 +30,23 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var items = Mocker.Resolve<DownloadClientRepository>().All();
var downloadClients = db.Query<DownloadClientDefinition81>("SELECT Settings FROM DownloadClients");
items.Should().HaveCount(1);
items.First().Settings.As<SabnzbdSettings>().TvCategory.Should().Be("abc");
downloadClients.Should().HaveCount(1);
downloadClients.First().Settings.ToObject<SabnzbdSettings81>().TvCategory.Should().Be("abc");
}
[Test]
public void should_be_updated_for_transmission()
{
WithTestDb(c =>
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("DownloadClients").Row(new
{
Enable = 1,
Name = "Trans",
Implementation = "Transmission",
Settings = new TransmissionSettings
Settings = new
{
Host = "127.0.0.1",
TvCategory = "abc"
@@ -58,24 +55,23 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var items = Mocker.Resolve<DownloadClientRepository>().All();
var downloadClients = db.Query<DownloadClientDefinition81>("SELECT Settings FROM DownloadClients");
items.Should().HaveCount(1);
items.First().Settings.As<TransmissionSettings>().TvCategory.Should().Be(".abc");
downloadClients.Should().HaveCount(1);
downloadClients.First().Settings.ToObject<TransmissionSettings81>().TvCategory.Should().Be(".abc");
}
[Test]
public void should_leave_empty_category_untouched()
{
WithTestDb(c =>
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("DownloadClients").Row(new
{
Enable = 1,
Name = "Trans",
Implementation = "Transmission",
Settings = new TransmissionSettings
Settings = new
{
Host = "127.0.0.1",
TvCategory = ""
@@ -84,11 +80,10 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var items = Mocker.Resolve<DownloadClientRepository>().All();
var downloadClients = db.Query<DownloadClientDefinition81>("SELECT Settings FROM DownloadClients");
items.Should().HaveCount(1);
items.First().Settings.As<TransmissionSettings>().TvCategory.Should().Be("");
downloadClients.Should().HaveCount(1);
downloadClients.First().Settings.ToObject<TransmissionSettings81>().TvCategory.Should().Be("");
}
}
}

View File

@@ -1,32 +1,28 @@
using System;
using System.Linq;
using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Datastore.Migration;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Datastore.Migration
{
[TestFixture]
public class update_quality_minmax_sizeFixture : MigrationTest<Core.Datastore.Migration.update_quality_minmax_size>
public class update_quality_minmax_sizeFixture : MigrationTest<update_quality_minmax_size>
{
[Test]
public void should_not_fail_if_empty()
{
WithTestDb(c =>
{
var db = WithMigrationTestDb();
});
var qualityDefinitions = db.Query<QualityDefinition84>("SELECT * FROM QualityDefinitions");
var items = Mocker.Resolve<QualityDefinitionRepository>().All();
items.Should().HaveCount(0);
qualityDefinitions.Should().BeEmpty();
}
[Test]
public void should_set_rawhd_to_null()
{
WithTestDb(c =>
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("QualityDefinitions").Row(new
{
@@ -44,17 +40,16 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var items = Mocker.Resolve<QualityDefinitionRepository>().All();
var qualityDefinitions = db.Query<QualityDefinition84>("SELECT * FROM QualityDefinitions");
items.Should().HaveCount(2);
items.First(v => v.Quality.Id == 10).MaxSize.Should().NotHaveValue();
qualityDefinitions.Should().HaveCount(2);
qualityDefinitions.First(v => v.Quality == 10).MaxSize.Should().NotHaveValue();
}
[Test]
public void should_set_zero_maxsize_to_null()
{
WithTestDb(c =>
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("QualityDefinitions").Row(new
{
@@ -65,17 +60,16 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var items = Mocker.Resolve<QualityDefinitionRepository>().All();
var qualityDefinitions = db.Query<QualityDefinition84>("SELECT * FROM QualityDefinitions");
items.Should().HaveCount(1);
items.First(v => v.Quality.Id == 1).MaxSize.Should().NotHaveValue();
qualityDefinitions.Should().HaveCount(1);
qualityDefinitions.First(v => v.Quality == 1).MaxSize.Should().NotHaveValue();
}
[Test]
public void should_preserve_values()
{
WithTestDb(c =>
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("QualityDefinitions").Row(new
{
@@ -93,11 +87,10 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var items = Mocker.Resolve<QualityDefinitionRepository>().All();
var qualityDefinitions = db.Query<QualityDefinition84>("SELECT * FROM QualityDefinitions");
items.Should().HaveCount(2);
items.First(v => v.Quality.Id == 1).MaxSize.Should().Be(100);
qualityDefinitions.Should().HaveCount(2);
qualityDefinitions.First(v => v.Quality == 1).MaxSize.Should().Be(100);
}
}
}

View File

@@ -1,30 +1,26 @@
using System;
using System.Linq;
using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Download;
using NzbDrone.Core.Download.Clients.Deluge;
using NzbDrone.Core.Download.Clients.Sabnzbd;
using NzbDrone.Core.Download.Clients.Transmission;
using NzbDrone.Core.Datastore.Migration;
using NzbDrone.Core.Test.Framework;
using System.Drawing;
namespace NzbDrone.Core.Test.Datastore.Migration
{
[TestFixture]
public class expand_transmission_urlbaseFixture : MigrationTest<Core.Datastore.Migration.expand_transmission_urlbase>
public class expand_transmission_urlbaseFixture : MigrationTest<expand_transmission_urlbase>
{
[Test]
public void should_not_fail_if_no_transmission()
{
WithTestDb(c =>
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("DownloadClients").Row(new
{
Enable = 1,
Name = "Deluge",
Implementation = "Deluge",
Settings = new DelugeSettings
Settings = new DelugeSettings85
{
Host = "127.0.0.1",
TvCategory = "abc",
@@ -34,51 +30,48 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var items = Mocker.Resolve<DownloadClientRepository>().All();
var items = db.Query<DownloadClientDefinition81>("SELECT * FROM DownloadClients");
items.Should().HaveCount(1);
items.First().Settings.As<DelugeSettings>().UrlBase.Should().Be("/my/");
items.First().Settings.ToObject<DelugeSettings85>().UrlBase.Should().Be("/my/");
}
[Test]
public void should_be_updated_for_transmission()
{
WithTestDb(c =>
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("DownloadClients").Row(new
{
Enable = 1,
Name = "Trans",
Implementation = "Transmission",
Settings = new TransmissionSettings
Settings = new TransmissionSettings81
{
Host = "127.0.0.1",
TvCategory = "abc",
UrlBase = null
TvCategory = "abc"
}.ToJson(),
ConfigContract = "TransmissionSettings"
});
});
var items = Mocker.Resolve<DownloadClientRepository>().All();
var items = db.Query<DownloadClientDefinition81>("SELECT * FROM DownloadClients");
items.Should().HaveCount(1);
items.First().Settings.As<TransmissionSettings>().UrlBase.Should().Be("/transmission/");
items.First().Settings.ToObject<TransmissionSettings81>().UrlBase.Should().Be("/transmission/");
}
[Test]
public void should_be_append_to_existing_urlbase()
{
WithTestDb(c =>
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("DownloadClients").Row(new
{
Enable = 1,
Name = "Trans",
Implementation = "Transmission",
Settings = new TransmissionSettings
Settings = new TransmissionSettings81
{
Host = "127.0.0.1",
TvCategory = "abc",
@@ -88,11 +81,10 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var items = Mocker.Resolve<DownloadClientRepository>().All();
var items = db.Query<DownloadClientDefinition81>("SELECT * FROM DownloadClients");
items.Should().HaveCount(1);
items.First().Settings.As<TransmissionSettings>().UrlBase.Should().Be("/my/url/transmission/");
items.First().Settings.ToObject<TransmissionSettings81>().UrlBase.Should().Be("/my/url/transmission/");
}
}
}

View File

@@ -2,19 +2,18 @@
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Notifications;
using NzbDrone.Core.Notifications.PushBullet;
using NzbDrone.Core.Notifications.Pushover;
using NzbDrone.Core.Datastore.Migration;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Datastore.Migration
{
[TestFixture]
public class pushbullet_device_idsFixture : MigrationTest<Core.Datastore.Migration.pushbullet_device_ids>
public class pushbullet_device_idsFixture : MigrationTest<pushbullet_device_ids>
{
[Test]
public void should_not_fail_if_no_pushbullet()
{
WithTestDb(c =>
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Notifications").Row(new
{
@@ -23,12 +22,12 @@ namespace NzbDrone.Core.Test.Datastore.Migration
OnUpgrade = false,
Name = "Pushover",
Implementation = "Pushover",
Settings = new PushoverSettings().ToJson(),
Settings = "{}",
ConfigContract = "PushoverSettings"
});
});
var items = Mocker.Resolve<NotificationRepository>().All();
var items = db.Query<Notification86>("SELECT * FROM Notifications");
items.Should().HaveCount(1);
}
@@ -36,7 +35,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
[Test]
public void should_not_fail_if_deviceId_is_not_set()
{
WithTestDb(c =>
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Notifications").Row(new
{
@@ -47,13 +46,13 @@ namespace NzbDrone.Core.Test.Datastore.Migration
Implementation = "PushBullet",
Settings = new
{
ApiKey = "my_api_key",
ApiKey = "my_api_key"
}.ToJson(),
ConfigContract = "PushBulletSettings"
});
});
var items = Mocker.Resolve<NotificationRepository>().All();
var items = db.Query<Notification86>("SELECT * FROM Notifications");
items.Should().HaveCount(1);
}
@@ -63,7 +62,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
{
var deviceId = "device_id";
WithTestDb(c =>
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Notifications").Row(new
{
@@ -81,10 +80,10 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var items = Mocker.Resolve<NotificationRepository>().All();
var items = db.Query<Notification86>("SELECT * FROM Notifications");
items.Should().HaveCount(1);
items.First().Settings.As<PushBulletSettings>().DeviceIds.First().Should().Be(deviceId);
items.First().Settings.ToObject<PushBulletSettings86>().DeviceIds.First().Should().Be(deviceId);
}
}
}

View File

@@ -2,21 +2,18 @@
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Notifications;
using NzbDrone.Core.Notifications.PushBullet;
using NzbDrone.Core.Datastore.Migration;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Datastore.Migration
{
[TestFixture]
public class pushbullet_devices_channels : MigrationTest<Core.Datastore.Migration.pushbullet_devices_channels_list>
public class pushbullet_devices_channels_listFixture : MigrationTest<pushbullet_devices_channels_list>
{
[Test]
public void should_convert_comma_separted_string_to_list()
{
var deviceId = "device_id";
WithTestDb(c =>
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Notifications").Row(new
{
@@ -34,11 +31,10 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var items = Mocker.Resolve<NotificationRepository>().All();
var items = db.Query<Notification86>("SELECT * FROM Notifications");
items.Should().HaveCount(1);
var settings = items.First().Settings.As<PushBulletSettings>();
settings.ChannelTags.Should().HaveCount(2);
items.First().Settings.ToObject<PushBulletSettings88>().ChannelTags.Should().HaveCount(2);
}
}
}

View File

@@ -3,8 +3,6 @@ using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Datastore.Migration;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Indexers.KickassTorrents;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Datastore.Migration
@@ -20,13 +18,13 @@ namespace NzbDrone.Core.Test.Datastore.Migration
// [TestCase("HTTP://KICKASS.SO")] Not sure if there is an easy way to do this, not sure if worth it.
public void should_replace_old_url(string oldUrl)
{
WithTestDb(c =>
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Indexers").Row(new
{
Name = "Kickass_wrong_url",
Implementation = "KickassTorrents",
Settings = new KickassTorrentsSettings
Settings = new KickassTorrentsSettings90
{
BaseUrl = oldUrl
}.ToJson(),
@@ -34,22 +32,22 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var items = Mocker.Resolve<IndexerRepository>().All().ToList();
var items = db.Query<IndexerDefinition90>("SELECT * FROM Indexers");
items.Should().HaveCount(1);
items.First().Settings.As<KickassTorrentsSettings>().BaseUrl.Should().Be("https://kat.cr");
items.First().Settings.ToObject<KickassTorrentsSettings90>().BaseUrl.Should().Be("https://kat.cr");
}
[Test]
public void should_not_replace_other_indexers()
{
WithTestDb(c =>
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Indexers").Row(new
{
Name = "not_kickass",
Implementation = "NotKickassTorrents",
Settings = new KickassTorrentsSettings
Settings = new KickassTorrentsSettings90
{
BaseUrl = "kickass.so",
}.ToJson(),
@@ -57,10 +55,10 @@ namespace NzbDrone.Core.Test.Datastore.Migration
});
});
var items = Mocker.Resolve<IndexerRepository>().All().ToList();
var items = db.Query<IndexerDefinition90>("SELECT * FROM Indexers");
items.Should().HaveCount(1);
items.First().Settings.As<KickassTorrentsSettings>().BaseUrl.Should().Be("kickass.so");
items.First().Settings.ToObject<KickassTorrentsSettings90>().BaseUrl.Should().Be("kickass.so");
}
}
}

View File

@@ -0,0 +1,35 @@
using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Datastore.Migration;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Datastore.Migration
{
[TestFixture]
public class add_ultrahd_quality_in_profilesFixture : MigrationTest<add_ultrahd_quality_in_profiles>
{
[Test]
public void should_add_ultrahd_to_old_profile()
{
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Profiles").Row(new
{
Id = 0,
Name = "SDTV",
Cutoff = 1,
Items = "[ { \"quality\": 1, \"allowed\": true } ]",
Language = 1
});
});
var profiles = db.Query<Profile70>("SELECT Items FROM Profiles LIMIT 1");
var items = profiles.First().Items;
items.Should().HaveCount(4);
items.Select(v => v.Quality).Should().BeEquivalentTo(1, 16, 18, 19);
items.Select(v => v.Allowed).Should().BeEquivalentTo(true, false, false, false);
}
}
}

View File

@@ -144,7 +144,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
history = new SabnzbdHistory() { Items = new List<SabnzbdHistoryItem>() };
Mocker.GetMock<ISabnzbdProxy>()
.Setup(s => s.GetHistory(It.IsAny<int>(), It.IsAny<int>(), It.IsAny<SabnzbdSettings>()))
.Setup(s => s.GetHistory(It.IsAny<int>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<SabnzbdSettings>()))
.Returns(history);
}
@@ -396,5 +396,22 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.SabnzbdTests
result.OutputRootFolders.Should().NotBeNull();
result.OutputRootFolders.First().Should().Be(@"O:\mymount".AsOsAgnostic());
}
[TestCase("0.6.9", false)]
[TestCase("0.7.0", true)]
[TestCase("0.8.0", true)]
[TestCase("1.0.0", true)]
[TestCase("1.0.0RC1", true)]
[TestCase("1.1.x", true)]
public void should_test_version(string version, bool expected)
{
Mocker.GetMock<ISabnzbdProxy>()
.Setup(v => v.GetVersion(It.IsAny<SabnzbdSettings>()))
.Returns(version);
var error = Subject.Test();
error.IsValid.Should().Be(expected);
}
}
}

View File

@@ -117,6 +117,11 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
_settings.TvCategory = "sonarr";
}
protected void GivenTvDirectory()
{
_settings.TvDirectory = @"C:/Downloads/Finished/sonarr";
}
protected void GivenFailedDownload()
{
Mocker.GetMock<ITransmissionProxy>()
@@ -242,6 +247,22 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
id.Should().NotBeNullOrEmpty();
}
[Test]
public void Download_with_TvDirectory_should_force_directory()
{
GivenTvDirectory();
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var id = Subject.Download(remoteEpisode);
id.Should().NotBeNullOrEmpty();
Mocker.GetMock<ITransmissionProxy>()
.Verify(v => v.AddTorrentFromData(It.IsAny<byte[]>(), @"C:/Downloads/Finished/sonarr", It.IsAny<TransmissionSettings>()), Times.Once());
}
[Test]
public void Download_with_category_should_force_directory()
{
@@ -276,6 +297,21 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
.Verify(v => v.AddTorrentFromData(It.IsAny<byte[]>(), @"C:/Downloads/Finished/transmission/sonarr", It.IsAny<TransmissionSettings>()), Times.Once());
}
[Test]
public void Download_without_TvDirectory_and_Category_should_use_default()
{
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var id = Subject.Download(remoteEpisode);
id.Should().NotBeNullOrEmpty();
Mocker.GetMock<ITransmissionProxy>()
.Verify(v => v.AddTorrentFromData(It.IsAny<byte[]>(), null, It.IsAny<TransmissionSettings>()), Times.Once());
}
[TestCase("magnet:?xt=urn:btih:ZPBPA2P6ROZPKRHK44D5OW6NHXU5Z6KR&tr=udp", "CBC2F069FE8BB2F544EAE707D75BCD3DE9DCF951")]
public void Download_should_get_hash_from_magnet_url(string magnetUrl, string expectedHash)
{
@@ -368,6 +404,24 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
items.First().Status.Should().Be(DownloadItemStatus.Downloading);
}
public void should_exclude_items_not_in_TvDirectory()
{
GivenTvDirectory();
_downloading.DownloadDir = @"C:/Downloads/Finished/sonarr/subdir";
GivenTorrents(new List<TransmissionTorrent>
{
_downloading,
_queued
});
var items = Subject.GetItems().ToList();
items.Count.Should().Be(1);
items.First().Status.Should().Be(DownloadItemStatus.Downloading);
}
[Test]
public void should_fix_forward_slashes()
{

View File

@@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:torrent="http://xmlns.ezrss.it/0.1/">
<channel>
<title>tv torrents RSS feed - KickassTorrents</title>
<link>http://kickass.to/</link>
<description>tv torrents RSS feed</description>
<item>
<title>Doctor Strang&eacute;r.E03.140512.HDTV.H264.720p-iPOP.avi [CTRG]</title>
<category>TV</category>
<author>http://kickass.to/user/2NE1/</author>
<link>http://kickass.to/doctor-stranger-e03-140512-hdtv-h264-720p-ipop-avi-ctrg-t9100648.html</link>
<guid>http://kickass.to/doctor-stranger-e03-140512-hdtv-h264-720p-ipop-avi-ctrg-t9100648.html</guid>
<pubDate>Mon, 12 May 2014 16:16:49 +0000</pubDate>
<torrent:contentLength>1205364736</torrent:contentLength>
<torrent:infoHash>208C4F7866612CC88BFEBC7C496FA72C2368D1C0</torrent:infoHash>
<torrent:magnetURI><![CDATA[magnet:?xt=urn:btih:208C4F7866612CC88BFEBC7C496FA72C2368D1C0&dn=doctor+stranger+e03+140512+hdtv+h264+720p+ipop+avi+ctrg&tr=udp%3A%2F%2Fopen.demonii.com%3A1337%2Fannounce]]></torrent:magnetURI>
<torrent:seeds>206</torrent:seeds>
<torrent:peers>311</torrent:peers>
<torrent:verified>1</torrent:verified>
<torrent:fileName>doctor.stranger.e03.140512.hdtv.h264.720p.ipop.avi.ctrg.torrent</torrent:fileName>
<enclosure url="http://torcache.net/torrent/208C4F7866612CC88BFEBC7C496FA72C2368D1C0.torrent?title=%5Bkickass.to%5Ddoctor.stranger.e03.140512.hdtv.h264.720p.ipop.avi.ctrg" length="1205364736" type="application/x-bittorrent" />
</item>
<item>
<title>Triangle.E03.140512.HDTV.XViD-iPOP.avi [CTRG]</title>
<category>TV</category>
<author>http://kickass.to/user/2NE1/</author>
<link>http://kickass.to/triangle-e03-140512-hdtv-xvid-ipop-avi-ctrg-t9100647.html</link>
<guid>http://kickass.to/triangle-e03-140512-hdtv-xvid-ipop-avi-ctrg-t9100647.html</guid>
<pubDate>Mon, 12 May 2014 16:16:31 +0000</pubDate>
<torrent:contentLength>677543936</torrent:contentLength>
<torrent:infoHash>BF22A53C9889A7D325F2A3D904E566B7DF4074EB</torrent:infoHash>
<torrent:magnetURI><![CDATA[magnet:?xt=urn:btih:BF22A53C9889A7D325F2A3D904E566B7DF4074EB&dn=triangle+e03+140512+hdtv+xvid+ipop+avi+ctrg&tr=udp%3A%2F%2Fopen.demonii.com%3A1337%2Fannounce]]></torrent:magnetURI>
<torrent:seeds>242</torrent:seeds>
<torrent:peers>374</torrent:peers>
<torrent:verified>1</torrent:verified>
<torrent:fileName>triangle.e03.140512.hdtv.xvid.ipop.avi.ctrg.torrent</torrent:fileName>
<enclosure url="http://torcache.net/torrent/BF22A53C9889A7D325F2A3D904E566B7DF4074EB.torrent?title=%5Bkickass.to%5Dtriangle.e03.140512.hdtv.xvid.ipop.avi.ctrg" length="677543936" type="application/x-bittorrent" />
</item>
<item>
<title>Triangle.E03.140512.HDTV.H264.720p-iPOP.avi [CTRG]</title>
<category>TV</category>
<author>http://kickass.to/user/2NE1/</author>
<link>http://kickass.to/triangle-e03-140512-hdtv-h264-720p-ipop-avi-ctrg-t9100646.html</link>
<guid>http://kickass.to/triangle-e03-140512-hdtv-h264-720p-ipop-avi-ctrg-t9100646.html</guid>
<pubDate>Mon, 12 May 2014 16:16:10 +0000</pubDate>
<torrent:contentLength>1196869632</torrent:contentLength>
<torrent:infoHash>8427BFB8884B8228364EBB9B3EA7D8B77E03A7BC</torrent:infoHash>
<torrent:magnetURI><![CDATA[magnet:?xt=urn:btih:8427BFB8884B8228364EBB9B3EA7D8B77E03A7BC&dn=triangle+e03+140512+hdtv+h264+720p+ipop+avi+ctrg&tr=udp%3A%2F%2Fopen.demonii.com%3A1337%2Fannounce]]></torrent:magnetURI>
<torrent:seeds>177</torrent:seeds>
<torrent:peers>268</torrent:peers>
<torrent:verified>1</torrent:verified>
<torrent:fileName>triangle.e03.140512.hdtv.h264.720p.ipop.avi.ctrg.torrent</torrent:fileName>
<enclosure url="http://torcache.net/torrent/8427BFB8884B8228364EBB9B3EA7D8B77E03A7BC.torrent?title=%5Bkickass.to%5Dtriangle.e03.140512.hdtv.h264.720p.ipop.avi.ctrg" length="1196869632" type="application/x-bittorrent" />
</item>
<item>
<title>Triangle.E03.140512.HDTV.X264.720p-BarosG_.avi [CTRG]</title>
<category>TV</category>
<author>http://kickass.to/user/2NE1/</author>
<link>http://kickass.to/triangle-e03-140512-hdtv-x264-720p-barosg-avi-ctrg-t9100644.html</link>
<guid>http://kickass.to/triangle-e03-140512-hdtv-x264-720p-barosg-avi-ctrg-t9100644.html</guid>
<pubDate>Mon, 12 May 2014 16:15:52 +0000</pubDate>
<torrent:contentLength>1418906266</torrent:contentLength>
<torrent:infoHash>5556B773893DB55287ECEC581E850B853163DB11</torrent:infoHash>
<torrent:magnetURI><![CDATA[magnet:?xt=urn:btih:5556B773893DB55287ECEC581E850B853163DB11&dn=triangle+e03+140512+hdtv+x264+720p+barosg+avi+ctrg&tr=udp%3A%2F%2Fopen.demonii.com%3A1337%2Fannounce]]></torrent:magnetURI>
<torrent:seeds>522</torrent:seeds>
<torrent:peers>785</torrent:peers>
<torrent:verified>1</torrent:verified>
<torrent:fileName>triangle.e03.140512.hdtv.x264.720p.barosg.avi.ctrg.torrent</torrent:fileName>
<enclosure url="http://torcache.net/torrent/5556B773893DB55287ECEC581E850B853163DB11.torrent?title=%5Bkickass.to%5Dtriangle.e03.140512.hdtv.x264.720p.barosg.avi.ctrg" length="1418906266" type="application/x-bittorrent" />
</item>
<item>
<title>Battlestar Galactica 1978 Dvd3 e09 e10 e11 e12 [NL] [FR] [ENG] Sub</title>
<description>
<![CDATA[In een afgelegen zonnestelsel leeft een mensenras op twaalf koloniewerelden. Ze zijn al eeuwen in oorlog met de Cylons, gevechtsrobots die ooit werden gemaakt door een allang verdwenen buitenaards reptielachtig ras. Met de hulp van de menselijke verrader Baltar zijn de Cylons erin geslaagd de mensheid vrijwel uit te roeien. Slechts een oorlogsschip kan aan de vernietiging ontkomen: de Battlestar Galactica van commandant Adama.
Met een vloot burgerschepen vol vluchtelingen vlucht de Galactica voor de Cylons. Adama besluit op zoek te gaan naar de legendarische 13e en laatste kolonie, genaamd Aarde. Tijdens de lange en gevaarlijke reis worden ze voortdurend bedreigd door de achtervolgende Cylons en andere gevaren.]]>
</description>
<category>TV</category>
<author>http://kickass.to/user/hendriknl/</author>
<link>http://kickass.to/battlestar-galactica-1978-dvd3-e09-e10-e11-e12-nl-fr-eng-sub-t9100642.html</link>
<guid>http://kickass.to/battlestar-galactica-1978-dvd3-e09-e10-e11-e12-nl-fr-eng-sub-t9100642.html</guid>
<pubDate>Mon, 12 May 2014 16:15:46 +0000</pubDate>
<torrent:contentLength>4680841216</torrent:contentLength>
<torrent:infoHash>3D293CAFEDAC595F6E55F9C284DD76862FE254F6</torrent:infoHash>
<torrent:magnetURI><![CDATA[magnet:?xt=urn:btih:3D293CAFEDAC595F6E55F9C284DD76862FE254F6&dn=battlestar+galactica+1978+dvd3+e09+e10+e11+e12+nl+fr+eng+sub&tr=udp%3A%2F%2Fopen.demonii.com%3A1337%2Fannounce]]></torrent:magnetURI>
<torrent:seeds>2</torrent:seeds>
<torrent:peers>5</torrent:peers>
<torrent:verified>0</torrent:verified>
<torrent:fileName>battlestar.galactica.1978.dvd3.e09.e10.e11.e12.nl.fr.eng.sub.torrent</torrent:fileName>
<enclosure url="http://torcache.net/torrent/3D293CAFEDAC595F6E55F9C284DD76862FE254F6.torrent?title=%5Bkickass.to%5Dbattlestar.galactica.1978.dvd3.e09.e10.e11.e12.nl.fr.eng.sub" length="4680841216" type="application/x-bittorrent" />
</item>
</channel>
</rss>

View File

@@ -0,0 +1,31 @@
<caps>
<server appversion="" version="0.1" />
<limits max="60" default="25"/>
<registration available="yes" open="no"/>
<searching>
<search available="yes"/>
<tv-search available="yes"/>
<movie-search available="yes"/>
<audio-search available="yes"/>
</searching>
<categories>
<category id="5000" name="TV">
<subcat id="5070" name="Anime"/>
<subcat id="5080" name="Documentary"/>
<subcat id="5020" name="Foreign"/>
<subcat id="5040" name="HD"/>
<subcat id="5050" name="Other"/>
<subcat id="5030" name="SD"/>
<subcat id="5060" name="Sport"/>
<subcat id="5010" name="WEB-DL"/>
</category>
<category id="7000" name="Other">
<subcat id="7010" name="Misc"/>
</category>
<category id="8000" name="Books">
<subcat id="8020" name="Comics"/>
</category>
</categories>
<groups></groups>
<genres></genres>
</caps>

View File

@@ -0,0 +1,204 @@
<?xml version='1.0' encoding='utf-8' ?>
<rss version='2.0'>
<channel>
<title><![CDATA[RSS ac.me, Category: TV. Torrents type: Most Downloaded. The World's Largest BitTorrent System]]></title>
<link>http://ac.me/</link>
<description>RSS ac.me The World's Largest BitTorrent System. Any torrents for download. Download music, movies, games, software, iPod, anime, porn, adult, books, pictures and other torrents.</description>
<language>en-us</language>
<category>All</category>
<webMaster>extratorr@gmail.com</webMaster>
<image>
<title>ac.me</title>
<url>http://ac.me/images/logo.gif</url>
<link>http://ac.me</link>
</image>
<item>
<title><![CDATA[One.Piece.E334.D ED.720p.HDTV.x264-W4F-={SPARROW}=-]]></title>
<pubDate>Sun, 21 Feb 2016 09:51:54 +0000</pubDate>
<category>TV</category>
<link>http://ac.me/torrent/4722030/One.Piece.E334.D+ED.720p.HDTV.x264-W4F-%3D%7BSPARROW%7D%3D-.html</link>
<enclosure url="http://ac.me/download/4722030/One.Piece.E334.D+ED.720p.HDTV.x264-W4F-%3D%7BSPARROW%7D%3D-.torrent" length="562386947" type="application/x-bittorrent" />
<guid isPermaLink="true">http://ac.me/torrent/4722030/One.Piece.E334.D+ED.720p.HDTV.x264-W4F-%3D%7BSPARROW%7D%3D-.html</guid>
<description>
<![CDATA[ <br />
<div class="bbcode_center" style="text-align:center"><br />
One.Piece.E334.DUBBED.720p.HDTV.x264-W4F-={SPARROW}=-<br /><br />
<br /><br />
<a href='http://www.sparrowpics.com/image/LwB' target='_blank' rel='nofollow' ><img src='http://www.sparrowpics.com/images/2015/12/10/Info.png' alt='Info.png' title='Info.png' border='0' /></a><br /><br />
<br /><br />
<span style="color:green"><br /><br />
one.piece.e334.720p.hdtv.x264-w4f-={SPARROW}=-.mkv<br /><br />
<br /><br />
File type: mkv<br /><br />
Duration: 00:21:14<br /><br />
Video size: 1280x720<br /><br />
Frame rate: 23.98<br /><br />
Bitrate: 3529 kb/s<br /><br />
Video codec: h264<br /><br />
Audio codec: ac3,<br /><br />
Audio type: 5.1(side) </span><br /><br />
<br /><br />
<a href='http://www.sparrowpics.com/image/UYe' target='_blank' rel='nofollow' ><img src='http://www.sparrowpics.com/images/2015/12/10/Screens.png' alt='Screens.png' title='Screens.png' border='0' /></a><br /><br />
<br /><br />
<span style="color:red">Click Image To View Full Size</span><br /><br />
<br /><br />
<a href='http://www.sparrowpics.com/image/FR1EP'... ]]>
</description>
<size>562386947</size>
<seeders>---</seeders>
<leechers>---</leechers>
<info_hash>c1b7641c4fd5fd4c248a7aee7c2ad0a4267a371c</info_hash>
</item>
<item>
<title><![CDATA[One Piece E334 D ED 720p HDTV x264-W4F]]></title>
<pubDate>Sun, 21 Feb 2016 09:44:21 +0000</pubDate>
<category>TV</category>
<link>http://ac.me/torrent/4722015/One+Piece+E334+D+ED+720p+HDTV+x264-W4F.html</link>
<enclosure url="http://ac.me/download/4722015/One+Piece+E334+D+ED+720p+HDTV+x264-W4F.torrent" length="562392556" type="application/x-bittorrent" />
<guid isPermaLink="true">http://ac.me/torrent/4722015/One+Piece+E334+D+ED+720p+HDTV+x264-W4F.html</guid>
<description>
<![CDATA[ <b></b><br /><br />
<br /><br />
<br /><br />
<br /><br />
<br /><br />
<b>one.piece.e334.720p.hdtv.x264-w4f.mkv</b><br /><br />
<br /><br />
<b>SIZE:</b> 562386319 bytes (536.33 MiB),<br /><br />
<br /><br />
<b>DURATION:</b> 00:21:14,<br /><br />
<br /><br />
<b>AVG-BITRATE:</b> 3531 kb/s<br /><br />
<br /><br />
<b>AUDIO:</b> ac3, 48000 Hz, 5:1 (eng)<br /><br />
<br /><br />
<b>VIDEO:</b> h264, yuv420p, 1280x720, 23.98 fps(r)<br /><br />
Subtitles: eng<br /><br />
<br /><br />
<br /><br />
<br /><br />
<br /><br />
<br /><br />
<b>SCREENS:</b><br /><br />
<a href='http://vivaex.com/img-56c986f4020e8.html' target='_blank' rel='nofollow' ><img src='http://vivaex.com/upload/small/2016/02/21/56c986f4020ae.jpg' alt='56c986f4020ae.jpg' title='56c986f4020ae.jpg' border='0' /></a><br /><br />
<br /><br />
<a href='http://vivaex.com/img-56c986f40a4b0.html' target='_blank' rel='nofollow' ><b>Large Runtime Screen</b></a><br /><br />
<br /><br />
<a href='http://vivaex.com/img-56c986f41229f.html' target='_blank' rel='nofollow' ><b>Large Runtime Screen</b></a> ]]>
</description>
<size>562392556</size>
<seeders>---</seeders>
<leechers>---</leechers>
<info_hash>1a69f565b531594e4f75b0fd4db153dce3e5186e</info_hash>
</item>
<item>
<title><![CDATA[Shadowhunters.S01E06.Of.Men.and.Angels.720p.HDTV.DD5.1.MPEG2-JiTB-={SPARROW}=-]]></title>
<pubDate>Sun, 21 Feb 2016 09:33:00 +0000</pubDate>
<category>TV</category>
<link>http://ac.me/torrent/4721983/Shadowhunters.S01E06.Of.Men.and.Angels.720p.HDTV.DD5.1.MPEG2-JiTB-%3D%7BSPARROW%7D%3D-.html</link>
<enclosure url="http://ac.me/download/4721983/Shadowhunters.S01E06.Of.Men.and.Angels.720p.HDTV.DD5.1.MPEG2-JiTB-%3D%7BSPARROW%7D%3D-.torrent" length="2826689668" type="application/x-bittorrent" />
<guid isPermaLink="true">http://ac.me/torrent/4721983/Shadowhunters.S01E06.Of.Men.and.Angels.720p.HDTV.DD5.1.MPEG2-JiTB-%3D%7BSPARROW%7D%3D-.html</guid>
<description>
<![CDATA[ <br />
<div class="bbcode_center" style="text-align:center"><br />
Shadowhunters.S01E06.Of.Men.and.Angels.720p.HDTV.DD5.1.MPEG2-JiTB-={SPARROW}=-<br /><br />
<br /><br />
<a href='http://www.sparrowpics.com/image/LwB' target='_blank' rel='nofollow' ><img src='http://www.sparrowpics.com/images/2015/12/10/Info.png' alt='Info.png' title='Info.png' border='0' /></a><br /><br />
<br /><br />
<span style="color:green"><br /><br />
Shadowhunters.S01E06.Of.Men.and.Angels.720p.HDTV.DD5.1.MPEG2-JiTB.ts<br /><br />
<br /><br />
File type: ts<br /><br />
Duration: 00:41:17<br /><br />
Video size: 1280x720<br /><br />
Frame rate: 59.94<br /><br />
Bitrate: 9126 kb/s<br /><br />
Video codec: mpeg2video<br /><br />
Audio codec: ac3<br /><br />
Audio type: 5.1(side) </span><br /><br />
<br /><br />
<a href='http://www.sparrowpics.com/image/UYe' target='_blank' rel='nofollow' ><img src='http://www.sparrowpics.com/images/2015/12/10/Screens.png' alt='Screens.png' title='Screens.png' border='0' /></a><br /><br />
<br /><br />
<span style="color:red">Click Image To View Full Size</span><br /><br />
<br /><br />
<a... ]]>
</description>
<size>2826689668</size>
<seeders>---</seeders>
<leechers>---</leechers>
<info_hash>e7b26a23c8cc7e8b2d7da35baaa5933a51586c90</info_hash>
</item>
<item>
<title><![CDATA[Shadowhunters.S01E05.Moo.Shu.to.Go.720p.HDTV.DD5.1.MPEG2-JiTB-={SPARROW}=-]]></title>
<pubDate>Sun, 21 Feb 2016 09:32:51 +0000</pubDate>
<category>TV</category>
<link>http://ac.me/torrent/4721982/Shadowhunters.S01E05.Moo.Shu.to.Go.720p.HDTV.DD5.1.MPEG2-JiTB-%3D%7BSPARROW%7D%3D-.html</link>
<enclosure url="http://ac.me/download/4721982/Shadowhunters.S01E05.Moo.Shu.to.Go.720p.HDTV.DD5.1.MPEG2-JiTB-%3D%7BSPARROW%7D%3D-.torrent" length="2823160720" type="application/x-bittorrent" />
<guid isPermaLink="true">http://ac.me/torrent/4721982/Shadowhunters.S01E05.Moo.Shu.to.Go.720p.HDTV.DD5.1.MPEG2-JiTB-%3D%7BSPARROW%7D%3D-.html</guid>
<description>
<![CDATA[ <br />
<div class="bbcode_center" style="text-align:center"><br />
Shadowhunters.S01E05.Moo.Shu.to.Go.720p.HDTV.DD5.1.MPEG2-JiTB-={SPARROW}=-<br /><br />
<br /><br />
<a href='http://www.sparrowpics.com/image/LwB' target='_blank' rel='nofollow' ><img src='http://www.sparrowpics.com/images/2015/12/10/Info.png' alt='Info.png' title='Info.png' border='0' /></a><br /><br />
<br /><br />
<span style="color:green"><br /><br />
Shadowhunters.S01E05.Moo.Shu.to.Go.720p.HDTV.DD5.1.MPEG2-JiTB.ts<br /><br />
<br /><br />
File type: ts<br /><br />
Duration: 00:41:18<br /><br />
Video size: 1280x720<br /><br />
Frame rate: 59.94<br /><br />
Bitrate: 9112 kb/s<br /><br />
Video codec: mpeg2video<br /><br />
Audio codec: ac3<br /><br />
Audio type: 5.1(side) </span><br /><br />
<br /><br />
<a href='http://www.sparrowpics.com/image/UYe' target='_blank' rel='nofollow' ><img src='http://www.sparrowpics.com/images/2015/12/10/Screens.png' alt='Screens.png' title='Screens.png' border='0' /></a><br /><br />
<br /><br />
<span style="color:red">Click Image To View Full Size</span><br /><br />
<br /><br />
<a... ]]>
</description>
<size>2823160720</size>
<seeders>---</seeders>
<leechers>---</leechers>
<info_hash>77faae6a126854fceb0a9a6fbdc229f68d3e3d03</info_hash>
</item>
<item>
<title><![CDATA[Second.Chance.2016.S01E05.Scratch.That.Glitch.720p.HDTV.DD5.1.MPEG2-JiTB-={SPARROW}=-]]></title>
<pubDate>Sun, 21 Feb 2016 09:32:47 +0000</pubDate>
<category>TV</category>
<link>http://ac.me/torrent/4721981/Second.Chance.2016.S01E05.Scratch.That.Glitch.720p.HDTV.DD5.1.MPEG2-JiTB-%3D%7BSPARROW%7D%3D-.html</link>
<enclosure url="http://ac.me/download/4721981/Second.Chance.2016.S01E05.Scratch.That.Glitch.720p.HDTV.DD5.1.MPEG2-JiTB-%3D%7BSPARROW%7D%3D-.torrent" length="4745525204" type="application/x-bittorrent" />
<guid isPermaLink="true">http://ac.me/torrent/4721981/Second.Chance.2016.S01E05.Scratch.That.Glitch.720p.HDTV.DD5.1.MPEG2-JiTB-%3D%7BSPARROW%7D%3D-.html</guid>
<description>
<![CDATA[ <br />
<div class="bbcode_center" style="text-align:center"><br />
Second.Chance.2016.S01E05.Scratch.That.Glitch.720p.HDTV.DD5.1.MPEG2-JiTB-={SPARROW}=-<br /><br />
<br /><br />
<a href='http://www.sparrowpics.com/image/LwB' target='_blank' rel='nofollow' ><img src='http://www.sparrowpics.com/images/2015/12/10/Info.png' alt='Info.png' title='Info.png' border='0' /></a><br /><br />
<br /><br />
<span style="color:green"><br /><br />
Second.Chance.2016.S01E05.Scratch.That.Glitch.720p.HDTV.DD5.1.MPEG2-JiTB.ts<br /><br />
<br /><br />
File type: ts<br /><br />
Duration: 00:42:01<br /><br />
Video size: 1280x720<br /><br />
Frame rate: 59.94<br /><br />
Bitrate: 15055 kb/s<br /><br />
Video codec: mpeg2video<br /><br />
Audio codec: ac3 ac3<br /><br />
Audio type: 5.1(side) stereo </span><br /><br />
<br /><br />
<a href='http://www.sparrowpics.com/image/UYe' target='_blank' rel='nofollow' ><img src='http://www.sparrowpics.com/images/2015/12/10/Screens.png' alt='Screens.png' title='Screens.png' border='0' /></a><br /><br />
<br /><br />
<span style="color:red">Click Image To View Full... ]]>
</description>
<size>4745525204</size>
<seeders>---</seeders>
<leechers>---</leechers>
<info_hash>0c341bbdadbc3c985304eb13893cc0731121e333</info_hash>
</item>
</channel>
</rss>

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using FluentMigrator;
@@ -7,11 +8,11 @@ using FluentMigrator.Runner;
using Marr.Data;
using Moq;
using NUnit.Framework;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Datastore.Migration.Framework;
using NzbDrone.Core.Messaging.Events;
namespace NzbDrone.Core.Test.Framework
{
public abstract class DbTest<TSubject, TModel> : DbTest
@@ -70,7 +71,6 @@ namespace NzbDrone.Core.Test.Framework
get
{
return MigrationType.Main;
}
}
@@ -85,10 +85,10 @@ namespace NzbDrone.Core.Test.Framework
}
}
protected virtual TestDatabase WithTestDb(Action<MigrationBase> beforeMigration)
protected virtual ITestDatabase WithTestDb(MigrationContext migrationContext)
{
var factory = Mocker.Resolve<DbFactory>();
var database = factory.Create(MigrationType, beforeMigration);
var database = factory.Create(migrationContext);
Mocker.SetConstant(database);
switch (MigrationType)
@@ -118,7 +118,6 @@ namespace NzbDrone.Core.Test.Framework
return testDb;
}
protected void SetupContainer()
{
WithTempAsAppPath();
@@ -134,7 +133,7 @@ namespace NzbDrone.Core.Test.Framework
public virtual void SetupDb()
{
SetupContainer();
_db = WithTestDb(null);
_db = WithTestDb(new MigrationContext(MigrationType));
}
[TearDown]
@@ -158,57 +157,4 @@ namespace NzbDrone.Core.Test.Framework
}
}
}
public interface ITestDatabase
{
void InsertMany<T>(IEnumerable<T> items) where T : ModelBase, new();
T Insert<T>(T item) where T : ModelBase, new();
List<T> All<T>() where T : ModelBase, new();
T Single<T>() where T : ModelBase, new();
void Update<T>(T childModel) where T : ModelBase, new();
void Delete<T>(T childModel) where T : ModelBase, new();
}
public class TestDatabase : ITestDatabase
{
private readonly IDatabase _dbConnection;
private IEventAggregator _eventAggregator;
public TestDatabase(IDatabase dbConnection)
{
_eventAggregator = new Mock<IEventAggregator>().Object;
_dbConnection = dbConnection;
}
public void InsertMany<T>(IEnumerable<T> items) where T : ModelBase, new()
{
new BasicRepository<T>(_dbConnection, _eventAggregator).InsertMany(items.ToList());
}
public T Insert<T>(T item) where T : ModelBase, new()
{
return new BasicRepository<T>(_dbConnection, _eventAggregator).Insert(item);
}
public List<T> All<T>() where T : ModelBase, new()
{
return new BasicRepository<T>(_dbConnection, _eventAggregator).All().ToList();
}
public T Single<T>() where T : ModelBase, new()
{
return All<T>().SingleOrDefault();
}
public void Update<T>(T childModel) where T : ModelBase, new()
{
new BasicRepository<T>(_dbConnection, _eventAggregator).Update(childModel);
}
public void Delete<T>(T childModel) where T : ModelBase, new()
{
new BasicRepository<T>(_dbConnection, _eventAggregator).Delete(childModel);
}
}
}

View File

@@ -0,0 +1,130 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Datastore;
namespace NzbDrone.Core.Test.Framework
{
public interface IDirectDataMapper
{
List<Dictionary<string, object>> Query(string sql);
List<T> Query<T>(string sql) where T : new();
}
public class DirectDataMapper : IDirectDataMapper
{
private readonly DbProviderFactory _providerFactory;
private readonly string _connectionString;
public DirectDataMapper(IDatabase database)
{
var dataMapper = database.GetDataMapper();
_providerFactory = dataMapper.ProviderFactory;
_connectionString = dataMapper.ConnectionString;
}
private DbConnection OpenConnection()
{
var connection = _providerFactory.CreateConnection();
connection.ConnectionString = _connectionString;
connection.Open();
return connection;
}
public DataTable GetDataTable(string sql)
{
using (var connection = OpenConnection())
{
using (var cmd = connection.CreateCommand())
{
var dataTable = new DataTable();
cmd.CommandText = sql;
dataTable.Load(cmd.ExecuteReader());
return dataTable;
}
}
}
public List<Dictionary<string, object>> Query(string sql)
{
var dataTable = GetDataTable(sql);
return dataTable.Rows.Cast<DataRow>().Select(MapToDictionary).ToList();
}
public List<T> Query<T>(string sql) where T : new()
{
var dataTable = GetDataTable(sql);
return dataTable.Rows.Cast<DataRow>().Select(MapToObject<T>).ToList();
}
protected Dictionary<string, object> MapToDictionary(DataRow dataRow)
{
var item = new Dictionary<string, object>();
for (var i = 0; i < dataRow.Table.Columns.Count; i++)
{
var columnName = dataRow.Table.Columns[i].ColumnName;
object value;
if (dataRow.ItemArray[i] == DBNull.Value)
{
value = null;
}
else
{
value = dataRow.ItemArray[i];
}
item[columnName] = dataRow.ItemArray[i];
}
return item;
}
protected T MapToObject<T>(DataRow dataRow) where T : new()
{
var item = new T();
for (var i = 0; i < dataRow.Table.Columns.Count; i++)
{
var columnName = dataRow.Table.Columns[i].ColumnName;
var propertyInfo = typeof(T).GetProperty(columnName);
if (propertyInfo == null)
{
throw new Exception(string.Format("Column {0} doesn't exist on type {1}.", columnName, typeof(T)));
}
var propertyType = propertyInfo.PropertyType;
if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
{
propertyType = propertyType.GetGenericArguments()[0];
}
object value;
if (dataRow.ItemArray[i] == DBNull.Value)
{
value = null;
}
else if (dataRow.Table.Columns[i].DataType == typeof(string) && propertyType != typeof(string))
{
value = Json.Deserialize((string)dataRow.ItemArray[i], propertyType);
}
else
{
value = Convert.ChangeType(dataRow.ItemArray[i], propertyType);
}
propertyInfo.SetValue(item, value, null);
}
return item;
}
}
}

View File

@@ -1,23 +1,41 @@
using System;
using System.Data;
using FluentMigrator;
using NUnit.Framework;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Datastore.Migration.Framework;
using NzbDrone.Test.Common.AutoMoq;
namespace NzbDrone.Core.Test.Framework
{
[Category("DbMigrationTest")]
[Category("DbTest")]
public abstract class MigrationTest<TMigration> : DbTest where TMigration : MigrationBase
public abstract class MigrationTest<TMigration> : DbTest where TMigration : NzbDroneMigrationBase
{
protected override TestDatabase WithTestDb(Action<MigrationBase> beforeMigration)
protected long MigrationVersion
{
return base.WithTestDb(m =>
get
{
if (m.GetType() == typeof(TMigration))
var attrib = (MigrationAttribute)Attribute.GetCustomAttribute(typeof(TMigration), typeof(MigrationAttribute));
return attrib.Version;
}
}
protected virtual IDirectDataMapper WithMigrationTestDb(Action<TMigration> beforeMigration = null)
{
var db = WithTestDb(new MigrationContext(MigrationType, MigrationVersion)
{
BeforeMigration = m =>
{
beforeMigration(m);
var migration = m as TMigration;
if (beforeMigration != null && migration is TMigration)
{
beforeMigration(migration);
}
}
});
return db.GetDirectDataMapper();
}
[SetUp]
@@ -25,5 +43,11 @@ namespace NzbDrone.Core.Test.Framework
{
SetupContainer();
}
[Obsolete("Don't use Mocker/Repositories in MigrationTests, query the DB.", true)]
public new AutoMoqer Mocker
{
get { return base.Mocker; }
}
}
}

View File

@@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using Moq;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Messaging.Events;
namespace NzbDrone.Core.Test.Framework
{
public interface ITestDatabase
{
void InsertMany<T>(IEnumerable<T> items) where T : ModelBase, new();
T Insert<T>(T item) where T : ModelBase, new();
List<T> All<T>() where T : ModelBase, new();
T Single<T>() where T : ModelBase, new();
void Update<T>(T childModel) where T : ModelBase, new();
void Delete<T>(T childModel) where T : ModelBase, new();
IDirectDataMapper GetDirectDataMapper();
}
public class TestDatabase : ITestDatabase
{
private readonly IDatabase _dbConnection;
private readonly IEventAggregator _eventAggregator;
public TestDatabase(IDatabase dbConnection)
{
_eventAggregator = new Mock<IEventAggregator>().Object;
_dbConnection = dbConnection;
}
public void InsertMany<T>(IEnumerable<T> items) where T : ModelBase, new()
{
new BasicRepository<T>(_dbConnection, _eventAggregator).InsertMany(items.ToList());
}
public T Insert<T>(T item) where T : ModelBase, new()
{
return new BasicRepository<T>(_dbConnection, _eventAggregator).Insert(item);
}
public List<T> All<T>() where T : ModelBase, new()
{
return new BasicRepository<T>(_dbConnection, _eventAggregator).All().ToList();
}
public T Single<T>() where T : ModelBase, new()
{
return All<T>().SingleOrDefault();
}
public void Update<T>(T childModel) where T : ModelBase, new()
{
new BasicRepository<T>(_dbConnection, _eventAggregator).Update(childModel);
}
public void Delete<T>(T childModel) where T : ModelBase, new()
{
new BasicRepository<T>(_dbConnection, _eventAggregator).Delete(childModel);
}
public IDirectDataMapper GetDirectDataMapper()
{
return new DirectDataMapper(_dbConnection);
}
}
}

View File

@@ -1,7 +0,0 @@
namespace NzbDrone.Core.Test.Framework
{
internal static class TestDbHelper
{
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Moq;
using NUnit.Framework;
using NzbDrone.Core.HealthCheck.Checks;
using NzbDrone.Core.Indexers;
@@ -10,17 +11,17 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
[TestFixture]
public class IndexerCheckFixture : CoreTest<IndexerCheck>
{
private IIndexer _indexer;
private Mock<IIndexer> _indexerMock;
private void GivenIndexer(bool supportsRss, bool supportsSearch)
{
var _indexer = Mocker.GetMock<IIndexer>();
_indexer.SetupGet(s => s.SupportsRss).Returns(supportsRss);
_indexer.SetupGet(s => s.SupportsSearch).Returns(supportsSearch);
_indexerMock = Mocker.GetMock<IIndexer>();
_indexerMock.SetupGet(s => s.SupportsRss).Returns(supportsRss);
_indexerMock.SetupGet(s => s.SupportsSearch).Returns(supportsSearch);
Mocker.GetMock<IIndexerFactory>()
.Setup(s => s.GetAvailableProviders())
.Returns(new List<IIndexer> { _indexer.Object });
.Returns(new List<IIndexer> { _indexerMock.Object });
Mocker.GetMock<IIndexerFactory>()
.Setup(s => s.RssEnabled())
@@ -35,14 +36,14 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
{
Mocker.GetMock<IIndexerFactory>()
.Setup(s => s.RssEnabled())
.Returns(new List<IIndexer> { _indexer });
.Returns(new List<IIndexer> { _indexerMock.Object });
}
private void GivenSearchEnabled()
{
Mocker.GetMock<IIndexerFactory>()
.Setup(s => s.SearchEnabled())
.Returns(new List<IIndexer> { _indexer });
.Returns(new List<IIndexer> { _indexerMock.Object });
}
[Test]

View File

@@ -22,8 +22,8 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
.Setup(s => s.StartUpFolder)
.Returns(@"C:\NzbDrone");
Mocker.GetMock<NzbDrone.Common.Disk.IDiskProvider>()
.Setup(c => c.FolderWritable(Moq.It.IsAny<string>()))
Mocker.GetMock<IDiskProvider>()
.Setup(c => c.FolderWritable(It.IsAny<string>()))
.Returns(false);
Subject.Check().ShouldBeError();
@@ -34,16 +34,45 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
{
MonoOnly();
const string startupFolder = @"/opt/nzbdrone";
Mocker.GetMock<IConfigFileProvider>()
.Setup(s => s.UpdateAutomatically)
.Returns(true);
Mocker.GetMock<IAppFolderInfo>()
.Setup(s => s.StartUpFolder)
.Returns(@"/opt/nzbdrone");
.Returns(startupFolder);
Mocker.GetMock<NzbDrone.Common.Disk.IDiskProvider>()
.Setup(c => c.FolderWritable(Moq.It.IsAny<string>()))
Mocker.GetMock<IDiskProvider>()
.Setup(c => c.FolderWritable(startupFolder))
.Returns(false);
Subject.Check().ShouldBeError();
}
[Test]
public void should_return_error_when_ui_folder_is_write_protected_and_update_automatically_is_enabled()
{
MonoOnly();
const string startupFolder = @"/opt/nzbdrone";
const string uiFolder = @"/opt/nzbdrone/UI";
Mocker.GetMock<IConfigFileProvider>()
.Setup(s => s.UpdateAutomatically)
.Returns(true);
Mocker.GetMock<IAppFolderInfo>()
.Setup(s => s.StartUpFolder)
.Returns(startupFolder);
Mocker.GetMock<IDiskProvider>()
.Setup(c => c.FolderWritable(startupFolder))
.Returns(true);
Mocker.GetMock<IDiskProvider>()
.Setup(c => c.FolderWritable(uiFolder))
.Returns(false);
Subject.Check().ShouldBeError();
@@ -66,8 +95,8 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
.Setup(s => s.StartUpFolder)
.Returns(@"/opt/nzbdrone");
Mocker.GetMock<NzbDrone.Common.Disk.IDiskProvider>()
.Verify(c => c.FolderWritable(Moq.It.IsAny<string>()), Times.Never());
Mocker.GetMock<IDiskProvider>()
.Verify(c => c.FolderWritable(It.IsAny<string>()), Times.Never());
Subject.Check().ShouldBeOk();
}

View File

@@ -23,6 +23,16 @@ namespace NzbDrone.Core.Test.Http
newRequest.Url.AbsoluteUri.Should().Be("http://torcache.net/download/123.torrent");
}
[Test]
public void should_add_referrer_torcache_request()
{
var request = new HttpRequest("http://torcache.net/download/123.torrent?title=something");
var newRequest = Subject.PreRequest(request);
newRequest.Headers.Should().Contain("Referer", "http://torcache.net/");
}
[TestCase("http://site.com/download?url=torcache.net&blaat=1")]
[TestCase("http://torcache.net.com/download?url=123")]
public void should_not_remove_query_params_from_other_requests(string url)

View File

@@ -226,7 +226,7 @@ namespace NzbDrone.Core.Test.IndexerSearchTests
var seasonNumber = 1;
var allCriteria = WatchForSearchCriteria();
Subject.SeasonSearch(_xemSeries.Id, seasonNumber, true);
Subject.SeasonSearch(_xemSeries.Id, seasonNumber, false);
var criteria = allCriteria.OfType<AnimeEpisodeSearchCriteria>().ToList();

Some files were not shown because too many files have changed in this diff Show More