1
0
mirror of https://github.com/Radarr/Radarr.git synced 2026-03-27 17:54:34 -04:00

Compare commits

...

153 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
Mark McDowall
2b72c0e328 Fixed: Manual Import Series selection
Closes #996
2016-01-09 13:16:34 -08:00
Mark McDowall
536aa350f0 Merge pull request #960 from Sonarr/nzb-vortex
NZBVortex Download Client
2016-01-07 15:53:57 -08:00
Mark McDowall
7c382c0e0c NZBVortex Download Client
New: NZBVortex Download Client
Closes #360
2016-01-07 15:50:52 -08:00
Mark McDowall
dda0d3259f Fixed broken test 2016-01-07 15:49:51 -08:00
Mark McDowall
a96718f7b3 Fixed Twitter notifications
New: Twitter notifications now require a Twitter (see settings for details)

Closes #1049
2016-01-06 22:32:12 -08:00
Mark McDowall
7ca67fe57a New: Special searching on RARBG 2016-01-05 23:07:49 -08:00
Mark McDowall
8373024f9d Fixed: Parsing of queued specials from download client queue 2016-01-05 22:56:34 -08:00
Mark McDowall
b62ef0c40c Fixed: Use folder quality when better than file quality (regression)
Closes #1022
2016-01-04 23:12:14 -08:00
Mark McDowall
376481eda5 Merge pull request #981 from Sonarr/ical-parameters
iCal parameters
2016-01-02 10:31:12 -08:00
Mark McDowall
800fa42982 Selectable range for iCal
New: Support for pastDays and fututeDays query parameters on iCal requests
Closes #974
2016-01-02 10:21:06 -08:00
Taloth Saldono
4e728c3a02 Increased timeout for Deluge to prevent timeout errors when posting large torrent files. 2015-12-30 22:50:17 +01:00
Taloth Saldono
663d254ced Fixed Ospath incorrectly detecting arbitrary colon as windows path. 2015-12-30 21:01:29 +01:00
vawen
8753c232c7 Fix: Paths with colons prevent Sonarr from communicating with Transmission
Issue #954
2015-12-29 13:25:36 +01:00
Taloth Saldono
221f3ef08c Safety net to handle MaxSize=0. Some users still have 0 = unlimited in their db and migration failed for them. 2015-12-28 20:24:24 +01:00
Taloth Saldono
b59175a87c Fixed: Indexer sites returning date as Retry-After header.
fixes #994
2015-12-28 20:24:23 +01:00
Taloth Saldono
37c621dcdb Fixed: Health Check produced warning if Sonarr binaries folder was not writable even when the external script update mechanism was selected.
fixes #964
2015-12-28 20:24:22 +01:00
Taloth Saldono
eaf3228bb7 Fixed Regex mistake in CleanLogMessage. 2015-12-28 20:24:21 +01:00
Jake Pusateri
c8debbf470 New: Better resolution posters on retina screens. 2015-12-28 11:12:12 -08:00
Mark McDowall
8dcd8d17b5 Fixed: Username must not be null or empty when logging in 2015-12-27 00:59:28 -08:00
Mark McDowall
cfe121c777 Don't return series as subtype for /api/episode
Fixed: Sped up loading episodes from server
2015-12-27 00:45:20 -08:00
Mark McDowall
b4f83d8a4e New: Media file extension .webm 2015-12-25 18:35:42 -08:00
Mark McDowall
9039d7e694 Fixed: Show a better error message when no episodes are parsed in a release 2015-12-25 18:32:03 -08:00
Taloth Saldono
7a25717da6 Fixed donate button. 2015-12-24 19:51:36 +01:00
Taloth Saldono
7e1c444c02 Fixed: Curl Fallback should ignore invalid cookies. 2015-12-24 19:30:16 +01:00
Mark McDowall
dc3f7c9bda Fixed: Improved parsing for single digit multi-episode titles
Closes #965
2015-12-20 00:11:41 -08:00
Mark McDowall
de754169fb Fixed: RSS Sync Interval validation 2015-12-19 18:02:38 -08:00
Mark McDowall
2d3c3bbb0c Changed torrent blackhole message 2015-12-19 17:49:54 -08:00
Mark McDowall
15cefe4a43 New: Option to Hardlink or Copy instead of move for Torrent Blackhole
Closes #1011
2015-12-19 17:18:22 -08:00
Mark McDowall
95da301975 A few UI Fixes
Closes #1009
Closes #1010
2015-12-18 23:41:30 -08:00
Mark McDowall
e03906b294 Fixed: Hardlink/Copy files from QBittorrent 2015-12-17 22:16:38 -08:00
Mark McDowall
7921dd3f96 Fixed: Removed Titans of TV tracker
Closes #992
2015-12-17 00:46:02 -08:00
Mark McDowall
9f066f7a6b New: Newznab preset for Usenet Crawler 2015-12-17 00:24:51 -08:00
Mark McDowall
81d131e732 Merge pull request #779 from cbodley/qbittorrent
Download client for qBittorrent
2015-12-15 23:10:20 -08:00
Casey Bodley
0552b56b71 qbittorrent: client plugin based heavily on uTorrent
supports a minimum qBittorrent version of 3.2.4, and uses labels for
v3.3.0 and later

Signed-off-by: Casey Bodley <cbodley@gmail.com>
2015-12-14 00:20:14 -05:00
Keivan Beigi
3952ee402b Update readme.md 2015-12-12 11:24:46 -08:00
Mark McDowall
0b3e27cb44 Don't keep dylibs for WIndows and Linux builds 2015-12-09 23:24:50 -08:00
Mark McDowall
4fa4b3507e Fixed: Force grabbing some delayed releases
Closes #984
2015-12-08 22:50:34 -08:00
Mark McDowall
8c211364e2 Fixed: Improved parsing of some multi-episode filenames 2015-12-08 15:26:52 -08:00
Mark McDowall
2d9917d074 Re-order regex to prefer [1x01] over 101 2015-12-06 11:03:11 -08:00
Mark McDowall
d514699ab7 Fixed: Prevent series from being added with an invalid Profile ID
Closes #977
2015-12-05 02:22:22 -08:00
Mark McDowall
dc176a83b3 Update CONTRIBUTING.md 2015-12-01 08:48:41 -08:00
Mark McDowall
69e3516a89 New: Allow Uppercase in Transmission category
Closes #934
2015-11-29 22:01:20 -08:00
Mark McDowall
c8a0f9fa7a Fixed: Saving settings changes 2015-11-26 12:05:37 -08:00
Mark McDowall
c2b9504b15 Merge pull request #931 from Dahlgren/osx-development
Include mediainfo and sqlite3 libraries for Mac
2015-11-24 18:35:07 -08:00
Mark McDowall
2693a3df2e Merge pull request #959 from roguecode/develop
Fixed: Indexer failure log message with local time
2015-11-24 15:41:57 -08:00
Matt
8062466ab8 Changing Indexer failure log message to local from UTC. 2015-11-24 23:42:20 +02:00
Björn Dahlgren
6cde1dd5ae Include mediainfo and sqlite3 libraries for Mac
Enables usage within MonoDevelop and Xamarin Studio including NUnit
2015-11-24 10:21:42 +01:00
Mark McDowall
b6c4a97675 Merge pull request #889 from Sonarr/quality-source
Folder quality when file quality determined by its extension
2015-11-23 23:01:10 -08:00
Mark McDowall
a9444cef30 Fixed: Folder quality when file quality determined by its extension
Closes #603
2015-11-23 23:00:51 -08:00
Mark McDowall
bf217a7093 Merge pull request #754 from Sonarr/real-releases
Support for REAL releases
2015-11-23 22:59:41 -08:00
Mark McDowall
b6b5355261 New: support for REAL releases
Closes #453

New: Added `Quality Real` naming Token
New: Quality Full will add real to file name when applicable
2015-11-23 22:58:53 -08:00
Mark McDowall
bc37084ec4 Merge pull request #928 from Dahlgren/mono-tests
Fixed tests for Mono
2015-11-23 22:50:34 -08:00
Mark McDowall
0a1a30f2af Merge pull request #953 from zetas/nn_preset_nzbcat
New: Newznab Preset for NZBCat
2015-11-23 22:50:15 -08:00
Keivan Beigi
7e023a7944 ConfigServiceFixture shouldn't be touching the DB. 2015-11-23 21:57:01 -08:00
zetas
91f68de8a7 Adding new newznab preset for NZBCat 2015-11-22 07:09:57 -05:00
Björn Dahlgren
994e2a6c57 Fixed failing tests on Mono
Test case unicode characters in escaped format
2015-11-22 01:11:43 +01:00
Mark McDowall
04da2d845a Merge pull request #941 from uzegonemad/hotfix/calendar-legend-width
Give calendar legend ul max width of 100%. Fixes #922
2015-11-18 22:12:39 -08:00
Benjamin Uzelac
d3b87bc3e8 give legend ul max width of 100%
give legend ul max width of 100%
2015-11-18 22:17:05 -06:00
417 changed files with 6571 additions and 8816 deletions

View File

@@ -2,5 +2,6 @@
<project version="4">
<component name="JavaScriptLibraryMappings">
<file url="file://$PROJECT_DIR$" libraries="{Sonarr node_modules}" />
<includedPredefinedLibrary name="ECMAScript 6" />
</component>
</project>

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.
@@ -16,7 +16,7 @@ Setup guides, FAQ, the more information we have on the wiki the better.
### Getting started ###
1. Fork Sonarr
2. Clone (develop branch)
2. Clone (develop branch) *you may need pull in submodules separately if you client doesn't clone them automatically (CurlSharp)*
3. Run `npm install`
4. Run `gulp watch` - Used to compile the UI components and copy them (leave this window open)
5. Compile in Visual Studio

264
build.ps1
View File

@@ -1,263 +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"
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
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

@@ -21,7 +21,7 @@ Sonarr is a PVR for Usenet and BitTorrent users. It can monitor multiple RSS fee
## Configuring Development Environment: ##
### Requirements ###
- Visual Studio 2013 [Free Community Edition](https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx)
- Visual Studio 2015 [Free Community Edition](https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx)
- [Git](http://git-scm.com/downloads)
- [NodeJS](http://nodejs.org/download/)
- [Gulp](http://gulpjs.com)
@@ -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

@@ -3,6 +3,7 @@ using Nancy;
using Nancy.Authentication.Forms;
using Nancy.Extensions;
using Nancy.ModelBinding;
using NzbDrone.Common.EnsureThat;
using NzbDrone.Core.Authentication;
using NzbDrone.Core.Configuration;
@@ -23,6 +24,11 @@ namespace NzbDrone.Api.Authentication
private Response Login(LoginResource resource)
{
Ensure.That(resource.Username, () => resource.Username).IsNotNullOrWhiteSpace();
// TODO: A null or empty password should not be allowed, uncomment in v3
//Ensure.That(resource.Password, () => resource.Password).IsNotNullOrWhiteSpace();
var user = _userService.FindUser(resource.Username, resource.Password);
if (user == null)

View File

@@ -22,15 +22,32 @@ namespace NzbDrone.Api.Calendar
private Response GetCalendarFeed()
{
var start = DateTime.Today.AddDays(-7);
var end = DateTime.Today.AddDays(28);
var pastDays = 7;
var futureDays = 28;
var start = DateTime.Today.AddDays(-pastDays);
var end = DateTime.Today.AddDays(futureDays);
// TODO: Remove start/end parameters in v3, they don't work well for iCal
var queryStart = Request.Query.Start;
var queryEnd = Request.Query.End;
var queryPastDays = Request.Query.PastDays;
var queryFutureDays = Request.Query.FutureDays;
if (queryStart.HasValue) start = DateTime.Parse(queryStart.Value);
if (queryEnd.HasValue) end = DateTime.Parse(queryEnd.Value);
if (queryPastDays.HasValue)
{
pastDays = int.Parse(queryPastDays.Value);
start = DateTime.Today.AddDays(-pastDays);
}
if (queryFutureDays.HasValue)
{
futureDays = int.Parse(queryFutureDays.Value);
end = DateTime.Today.AddDays(futureDays);
}
var episodes = _episodeService.EpisodesBetweenDates(start, end, false);
var icalCalendar = new iCalendar();

View File

@@ -1,4 +1,5 @@
using FluentValidation;
using NzbDrone.Api.Validation;
using NzbDrone.Core.Configuration;
namespace NzbDrone.Api.Config
@@ -16,8 +17,7 @@ namespace NzbDrone.Api.Config
.GreaterThanOrEqualTo(0);
SharedValidator.RuleFor(c => c.RssSyncInterval)
.InclusiveBetween(10, 120)
.When(c => c.RssSyncInterval > 0);
.IsValidRssSyncInterval();
}
}
}

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;
}
@@ -36,5 +36,10 @@ namespace NzbDrone.Api.Episodes
{
_episodeService.SetEpisodeMonitored(episodeResource.Id, episodeResource.Monitored);
}
protected override List<EpisodeResource> LoadSeries(List<EpisodeResource> resources)
{
return resources;
}
}
}
}

View File

@@ -79,7 +79,8 @@ namespace NzbDrone.Api.Episodes
{
var resources = base.ToListResource(modelList);
return resources.LoadSubtype<EpisodeResource, SeriesResource, Core.Tv.Series>(e => e.SeriesId, _seriesService.GetSeries).ToList();
return LoadSeries(resources);
}
public void Handle(EpisodeGrabbedEvent message)
@@ -100,5 +101,10 @@ namespace NzbDrone.Api.Episodes
BroadcastResourceChange(ModelAction.Updated, episode.Id);
}
}
protected virtual List<EpisodeResource> LoadSeries(List<EpisodeResource> resources)
{
return resources.LoadSubtype<EpisodeResource, SeriesResource, Core.Tv.Series>(e => e.SeriesId, _seriesService.GetSeries).ToList();
}
}
}
}

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>
@@ -238,6 +239,7 @@
<Compile Include="TinyIoCNancyBootstrapper.cs" />
<Compile Include="Update\UpdateModule.cs" />
<Compile Include="Update\UpdateResource.cs" />
<Compile Include="Validation\RssSyncIntervalValidator.cs" />
<Compile Include="Validation\EmptyCollectionValidator.cs" />
<Compile Include="Validation\RuleBuilderExtensions.cs" />
<Compile Include="Wanted\CutoffModule.cs" />
@@ -270,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

@@ -10,11 +10,11 @@ using NzbDrone.Core.MediaFiles.Events;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.SeriesStats;
using NzbDrone.Core.Tv;
using NzbDrone.Api.Validation;
using NzbDrone.Api.Mapping;
using NzbDrone.Core.Tv.Events;
using NzbDrone.Core.Validation.Paths;
using NzbDrone.Core.DataAugmentation.Scene;
using NzbDrone.Core.Validation;
using NzbDrone.SignalR;
namespace NzbDrone.Api.Series
@@ -43,7 +43,8 @@ namespace NzbDrone.Api.Series
SeriesPathValidator seriesPathValidator,
SeriesExistsValidator seriesExistsValidator,
DroneFactoryValidator droneFactoryValidator,
SeriesAncestorValidator seriesAncestorValidator
SeriesAncestorValidator seriesAncestorValidator,
ProfileExistsValidator profileExistsValidator
)
: base(signalRBroadcaster)
{
@@ -59,7 +60,7 @@ namespace NzbDrone.Api.Series
UpdateResource = UpdateSeries;
DeleteResource = DeleteSeries;
SharedValidator.RuleFor(s => s.ProfileId).ValidId();
Validation.RuleBuilderExtensions.ValidId(SharedValidator.RuleFor(s => s.ProfileId));
SharedValidator.RuleFor(s => s.Path)
.Cascade(CascadeMode.StopOnFirstFailure)
@@ -70,6 +71,8 @@ namespace NzbDrone.Api.Series
.SetValidator(seriesAncestorValidator)
.When(s => !s.Path.IsNullOrWhiteSpace());
SharedValidator.RuleFor(s => s.ProfileId).SetValidator(profileExistsValidator);
PostValidator.RuleFor(s => s.Path).IsValidPath().When(s => s.RootFolderPath.IsNullOrWhiteSpace());
PostValidator.RuleFor(s => s.RootFolderPath).IsValidPath().When(s => s.Path.IsNullOrWhiteSpace());
PostValidator.RuleFor(s => s.Title).NotEmpty();

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

@@ -0,0 +1,34 @@
using FluentValidation.Validators;
namespace NzbDrone.Api.Validation
{
public class RssSyncIntervalValidator : PropertyValidator
{
public RssSyncIntervalValidator()
: base("Must be between 10 and 120 or 0 to disable")
{
}
protected override bool IsValid(PropertyValidatorContext context)
{
if (context.PropertyValue == null)
{
return true;
}
var value = (int)context.PropertyValue;
if (value == 0)
{
return true;
}
if (value >= 10 && value <= 120)
{
return true;
}
return false;
}
}
}

View File

@@ -31,5 +31,10 @@ namespace NzbDrone.Api.Validation
{
return ruleBuilder.SetValidator(new EmptyCollectionValidator<TProp>());
}
public static IRuleBuilderOptions<T, int> IsValidRssSyncInterval<T>(this IRuleBuilder<T, int> ruleBuilder)
{
return ruleBuilder.SetValidator(new RssSyncIntervalValidator());
}
}
}

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

@@ -349,6 +349,33 @@ namespace NzbDrone.Common.Test.Http
Thread.CurrentThread.CurrentUICulture = origCulture;
}
}
[TestCase("lang_code=en; expires=Fri, 23-Dec-2016 18:09:14 GMT; Max-Age=31536000; path=/; domain=.abc.com")]
public void should_reject_malformed_domain_cookie(string malformedCookie)
{
try
{
// the date is bad in the below - should be 13-Jul-2016
string url = "http://eu.httpbin.org/response-headers?Set-Cookie=" + Uri.EscapeUriString(malformedCookie);
var requestSet = new HttpRequest(url);
requestSet.AllowAutoRedirect = false;
requestSet.StoreResponseCookie = true;
var responseSet = Subject.Get(requestSet);
var request = new HttpRequest("http://eu.httpbin.org/get");
var response = Subject.Get<HttpBinResource>(request);
response.Resource.Headers.Should().NotContainKey("Cookie");
ExceptionVerification.IgnoreErrors();
}
finally
{
}
}
}
public class HttpBinResource

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

@@ -24,6 +24,7 @@ namespace NzbDrone.Common.Test
[TestCase("/rooted/linux/path", OsPathKind.Unix)]
[TestCase("/", OsPathKind.Unix)]
[TestCase("linux/path", OsPathKind.Unix)]
[TestCase(@"Castle:unrooted+linux+path", OsPathKind.Unknown)]
public void should_auto_detect_kind(string path, OsPathKind kind)
{
var result = new OsPath(path);
@@ -94,6 +95,8 @@ namespace NzbDrone.Common.Test
[TestCase(@"rooted\windows\path")]
[TestCase(@"path")]
[TestCase("linux/path")]
[TestCase(@"Castle:unrooted+linux+path")]
[TestCase(@"C:unrooted+linux+path")]
public void should_detect_unrooted_ospaths(string path)
{
var osPath = new OsPath(path);

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

@@ -44,7 +44,7 @@ namespace NzbDrone.Common.Disk
{
return OsPathKind.Unix;
}
if (path.Contains(':') || path.Contains('\\'))
if (HasWindowsDriveLetter(path) || path.Contains('\\'))
{
return OsPathKind.Windows;
}
@@ -55,6 +55,15 @@ namespace NzbDrone.Common.Disk
return OsPathKind.Unknown;
}
private static bool HasWindowsDriveLetter(string path)
{
if (path.Length < 2) return false;
if (!char.IsLetter(path[0]) || path[1] != ':') return false;
if (path.Length > 2 && path[2] != '\\' && path[2] != '/') return false;
return true;
}
private static string FixSlashes(string path, OsPathKind kind)
{
switch (kind)
@@ -97,7 +106,7 @@ namespace NzbDrone.Common.Disk
{
if (IsWindowsPath)
{
return _path.StartsWith(@"\\") || _path.Contains(':');
return _path.StartsWith(@"\\") || HasWindowsDriveLetter(_path);
}
if (IsUnixPath)
{

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

@@ -92,5 +92,13 @@ namespace NzbDrone.Common.Extensions
return "\"" + text + "\"";
}
public static byte[] HexToByteArray(this string input)
{
return Enumerable.Range(0, input.Length)
.Where(x => x%2 == 0)
.Select(x => Convert.ToByte(input.Substring(x, 2), 16))
.ToArray();
}
}
}

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));
}
}
}
@@ -165,7 +173,14 @@ namespace NzbDrone.Common.Http.Dispatchers
var setCookie = webHeaderCollection.Get("Set-Cookie");
if (setCookie != null && setCookie.Length > 0 && cookies != null)
{
cookies.SetCookies(request.Url, FixSetCookieHeader(setCookie));
try
{
cookies.SetCookies(request.Url, FixSetCookieHeader(setCookie));
}
catch (CookieException ex)
{
_logger.Debug("Rejected cookie {0}: {1}", ex.InnerException.Message, setCookie);
}
}
return webHeaderCollection;

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

@@ -14,7 +14,18 @@ namespace NzbDrone.Common.Http
{
if (response.Headers.ContainsKey("Retry-After"))
{
RetryAfter = TimeSpan.FromSeconds(int.Parse(response.Headers["Retry-After"].ToString()));
var retryAfter = response.Headers["Retry-After"].ToString();
int seconds;
DateTime date;
if (int.TryParse(retryAfter, out seconds))
{
RetryAfter = TimeSpan.FromSeconds(seconds);
}
else if (DateTime.TryParse(retryAfter, out date))
{
RetryAfter = date.ToUniversalTime() - DateTime.UtcNow;
}
}
}
}

View File

@@ -9,11 +9,12 @@ 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 | RegexOptions.IgnoreCase),
new Regex(@"/fetch/[a-z0-9]{32}/(?<secret>[a-z0-9]{32})", RegexOptions.Compiled),
// Path
new Regex(@"""C:\\Users\\(?<secret>[^\""]+?)(\\|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase),
@@ -27,7 +28,7 @@ namespace NzbDrone.Common.Instrumentation
new Regex(@"""email_(account|to|from|pwd)""\s*:\s*""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
// uTorrent
new Regex(@"\[""[a-z._]*(|username|password)"",\d,""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
new Regex(@"\[""[a-z._]*(username|password)"",\d,""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
new Regex(@"\[""(boss_key|boss_key_salt|proxy\.proxy)"",\d,""(?<secret>[^""]+?)""", RegexOptions.Compiled | RegexOptions.IgnoreCase),
// BroadcastheNet
@@ -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

@@ -1,110 +1,59 @@
using System;
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.Configuration
{
[TestFixture]
public class ConfigServiceFixture : DbTest<ConfigService, Config>
public class ConfigServiceFixture : TestBase<ConfigService>
{
[SetUp]
public void SetUp()
{
Mocker.SetConstant<IConfigRepository>(Mocker.Resolve<ConfigRepository>());
Db.All<Config>().ForEach(Db.Delete);
}
[Test]
public void Add_new_value_to_database()
{
const string key = "MY_KEY";
const string value = "MY_VALUE";
const string key = "RssSyncInterval";
const int value = 12;
Subject.SetValue(key, value);
Subject.GetValue(key, "").Should().Be(value);
}
Subject.RssSyncInterval = value;
[Test]
public void Get_value_from_database()
{
const string key = "MY_KEY";
const string value = "MY_VALUE";
Db.Insert(new Config { Key = key, Value = value });
Db.Insert(new Config { Key = "Other Key", Value = "OtherValue" });
var result = Subject.GetValue(key, "");
result.Should().Be(value);
AssertUpsert(key, value);
}
[Test]
public void Get_value_should_return_default_when_no_value()
{
const string key = "MY_KEY";
const string value = "MY_VALUE";
var result = Subject.GetValue(key, value);
result.Should().Be(value);
}
[Test]
public void New_value_should_update_old_value_new_value()
{
const string key = "MY_KEY";
const string originalValue = "OLD_VALUE";
const string newValue = "NEW_VALUE";
Db.Insert(new Config { Key = key, Value = originalValue });
Subject.SetValue(key, newValue);
var result = Subject.GetValue(key, "");
result.Should().Be(newValue);
AllStoredModels.Should().HaveCount(1);
}
[Test]
public void New_value_should_update_old_value_same_value()
{
const string key = "MY_KEY";
const string value = "OLD_VALUE";
Subject.SetValue(key, value);
Subject.SetValue(key, value);
var result = Subject.GetValue(key, "");
result.Should().Be(value);
AllStoredModels.Should().HaveCount(1);
Subject.RssSyncInterval.Should().Be(15);
}
[Test]
public void get_value_with_persist_should_store_default_value()
{
const string key = "MY_KEY";
string value = Guid.NewGuid().ToString();
Subject.GetValue(key, value, persist: true).Should().Be(value);
Subject.GetValue(key, string.Empty).Should().Be(value);
var salt = Subject.HmacSalt;
salt.Should().NotBeNullOrWhiteSpace();
AssertUpsert("HmacSalt", salt);
}
[Test]
public void get_value_with_out_persist_should_not_store_default_value()
{
const string key = "MY_KEY";
string value1 = Guid.NewGuid().ToString();
string value2 = Guid.NewGuid().ToString();
var interval = Subject.RssSyncInterval;
interval.Should().Be(15);
Mocker.GetMock<IConfigRepository>().Verify(c => c.Insert(It.IsAny<Config>()), Times.Never());
}
Subject.GetValue(key, value1).Should().Be(value1);
Subject.GetValue(key, value2).Should().Be(value2);
private void AssertUpsert(string key, object value)
{
Mocker.GetMock<IConfigRepository>().Verify(c => c.Upsert(key.ToLowerInvariant(), value.ToString()));
}
[Test]
@@ -114,7 +63,16 @@ namespace NzbDrone.Core.Test.Configuration
var configProvider = Subject;
var allProperties = typeof(ConfigService).GetProperties().Where(p => p.GetSetMethod() != null).ToList();
var keys = new List<string>();
var values = new List<Config>();
Mocker.GetMock<IConfigRepository>().Setup(c => c.Upsert(It.IsAny<string>(), It.IsAny<string>())).Callback<string, string>((key, value) =>
{
keys.Add(key);
values.Add(new Config { Key = key, Value = value });
});
Mocker.GetMock<IConfigRepository>().Setup(c => c.All()).Returns(values);
foreach (var propertyInfo in allProperties)
{
@@ -148,8 +106,7 @@ namespace NzbDrone.Core.Test.Configuration
returnValue.Should().Be(value, propertyInfo.Name);
}
AllStoredModels.Should()
.HaveSameCount(allProperties, "two different properties are writing to the same key in db. Copy/Past fail.");
keys.Should().OnlyHaveUniqueItems();
}
}
}

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

@@ -0,0 +1,300 @@
using System;
using System.Linq;
using System.Collections.Generic;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Core.Download;
using NzbDrone.Core.Download.Clients.Nzbget;
using NzbDrone.Test.Common;
using NzbDrone.Core.RemotePathMappings;
using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Download.Clients;
using NzbDrone.Core.Download.Clients.NzbVortex;
using NzbDrone.Core.Download.Clients.NzbVortex.Responses;
namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbVortexTests
{
[TestFixture]
public class NzbVortexFixture : DownloadClientFixtureBase<NzbVortex>
{
private NzbVortexQueueItem _queued;
private NzbVortexQueueItem _failed;
private NzbVortexQueueItem _completed;
[SetUp]
public void Setup()
{
Subject.Definition = new DownloadClientDefinition();
Subject.Definition.Settings = new NzbVortexSettings
{
Host = "127.0.0.1",
Port = 2222,
ApiKey = "1234-ABCD",
TvCategory = "tv",
RecentTvPriority = (int)NzbgetPriority.High
};
_queued = new NzbVortexQueueItem
{
Id = RandomNumber,
DownloadedSize = 1000,
TotalDownloadSize = 10,
GroupName = "tv",
UiTitle = "Droned.S01E01.Pilot.1080p.WEB-DL-DRONE"
};
_failed = new NzbVortexQueueItem
{
DownloadedSize = 1000,
TotalDownloadSize = 1000,
GroupName = "tv",
UiTitle = "Droned.S01E01.Pilot.1080p.WEB-DL-DRONE",
DestinationPath = "somedirectory",
State = NzbVortexStateType.UncompressFailed,
};
_completed = new NzbVortexQueueItem
{
DownloadedSize = 1000,
TotalDownloadSize = 1000,
GroupName = "tv",
UiTitle = "Droned.S01E01.Pilot.1080p.WEB-DL-DRONE",
DestinationPath = "/remote/mount/tv/Droned.S01E01.Pilot.1080p.WEB-DL-DRONE",
State = NzbVortexStateType.Done
};
}
protected void GivenFailedDownload()
{
Mocker.GetMock<INzbVortexProxy>()
.Setup(s => s.DownloadNzb(It.IsAny<byte[]>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<NzbVortexSettings>()))
.Returns((string)null);
}
protected void GivenSuccessfulDownload()
{
Mocker.GetMock<INzbVortexProxy>()
.Setup(s => s.DownloadNzb(It.IsAny<byte[]>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<NzbVortexSettings>()))
.Returns(Guid.NewGuid().ToString().Replace("-", ""));
}
protected virtual void GivenQueue(NzbVortexQueueItem queue)
{
var list = new List<NzbVortexQueueItem>();
list.AddIfNotNull(queue);
Mocker.GetMock<INzbVortexProxy>()
.Setup(s => s.GetQueue(It.IsAny<int>(), It.IsAny<NzbVortexSettings>()))
.Returns(new NzbVortexQueue
{
Items = list
});
}
[Test]
public void GetItems_should_return_no_items_when_queue_is_empty()
{
GivenQueue(null);
Subject.GetItems().Should().BeEmpty();
}
[Test]
public void queued_item_should_have_required_properties()
{
GivenQueue(_queued);
var result = Subject.GetItems().Single();
VerifyQueued(result);
}
[Test]
public void paused_item_should_have_required_properties()
{
_queued.IsPaused = true;
GivenQueue(_queued);
var result = Subject.GetItems().Single();
VerifyPaused(result);
}
[Test]
public void downloading_item_should_have_required_properties()
{
_queued.State = NzbVortexStateType.Downloading;
GivenQueue(_queued);
var result = Subject.GetItems().Single();
VerifyDownloading(result);
}
[Test]
public void completed_download_should_have_required_properties()
{
GivenQueue(_completed);
var result = Subject.GetItems().Single();
VerifyCompleted(result);
}
[Test]
public void failed_item_should_have_required_properties()
{
GivenQueue(_failed);
var result = Subject.GetItems().Single();
VerifyFailed(result);
}
[Test]
public void should_report_UncompressFailed_as_failed()
{
_queued.State = NzbVortexStateType.UncompressFailed;
GivenQueue(_failed);
var items = Subject.GetItems();
items.First().Status.Should().Be(DownloadItemStatus.Failed);
}
[Test]
public void should_report_CheckFailedDataCorrupt_as_failed()
{
_queued.State = NzbVortexStateType.CheckFailedDataCorrupt;
GivenQueue(_failed);
var result = Subject.GetItems().Single();
result.Status.Should().Be(DownloadItemStatus.Failed);
}
[Test]
public void should_report_BadlyEncoded_as_failed()
{
_queued.State = NzbVortexStateType.BadlyEncoded;
GivenQueue(_failed);
var items = Subject.GetItems();
items.First().Status.Should().Be(DownloadItemStatus.Failed);
}
[Test]
public void Download_should_return_unique_id()
{
GivenSuccessfulDownload();
var remoteEpisode = CreateRemoteEpisode();
var id = Subject.Download(remoteEpisode);
id.Should().NotBeNullOrEmpty();
}
[Test]
public void Download_should_throw_if_failed()
{
GivenFailedDownload();
var remoteEpisode = CreateRemoteEpisode();
Assert.Throws<DownloadClientException>(() => Subject.Download(remoteEpisode));
}
[Test]
public void GetItems_should_ignore_downloads_from_other_categories()
{
_completed.GroupName = "mycat";
GivenQueue(null);
var items = Subject.GetItems();
items.Should().BeEmpty();
}
[Test]
public void should_remap_storage_if_mounted()
{
Mocker.GetMock<IRemotePathMappingService>()
.Setup(v => v.RemapRemoteToLocal("127.0.0.1", It.IsAny<OsPath>()))
.Returns(new OsPath(@"O:\mymount\Droned.S01E01.Pilot.1080p.WEB-DL-DRONE".AsOsAgnostic()));
GivenQueue(_completed);
var result = Subject.GetItems().Single();
result.OutputPath.Should().Be(@"O:\mymount\Droned.S01E01.Pilot.1080p.WEB-DL-DRONE".AsOsAgnostic());
}
[Test]
public void should_get_files_if_completed_download_is_not_in_a_job_folder()
{
Mocker.GetMock<IRemotePathMappingService>()
.Setup(v => v.RemapRemoteToLocal("127.0.0.1", It.IsAny<OsPath>()))
.Returns(new OsPath(@"O:\mymount\".AsOsAgnostic()));
Mocker.GetMock<INzbVortexProxy>()
.Setup(s => s.GetFiles(It.IsAny<int>(), It.IsAny<NzbVortexSettings>()))
.Returns(new NzbVortexFiles{ Files = new List<NzbVortexFile> { new NzbVortexFile { FileName = "Droned.S01E01.Pilot.1080p.WEB-DL-DRONE.mkv" } } });
_completed.State = NzbVortexStateType.Done;
GivenQueue(_completed);
var result = Subject.GetItems().Single();
result.OutputPath.Should().Be(@"O:\mymount\Droned.S01E01.Pilot.1080p.WEB-DL-DRONE.mkv".AsOsAgnostic());
}
[Test]
public void should_be_warning_if_more_than_one_file_is_not_in_a_job_folder()
{
Mocker.GetMock<IRemotePathMappingService>()
.Setup(v => v.RemapRemoteToLocal("127.0.0.1", It.IsAny<OsPath>()))
.Returns(new OsPath(@"O:\mymount\".AsOsAgnostic()));
Mocker.GetMock<INzbVortexProxy>()
.Setup(s => s.GetFiles(It.IsAny<int>(), It.IsAny<NzbVortexSettings>()))
.Returns(new NzbVortexFiles { Files = new List<NzbVortexFile>
{
new NzbVortexFile { FileName = "Droned.S01E01.Pilot.1080p.WEB-DL-DRONE.mkv" },
new NzbVortexFile { FileName = "Droned.S01E01.Pilot.1080p.WEB-DL-DRONE.nfo" }
} });
_completed.State = NzbVortexStateType.Done;
GivenQueue(_completed);
var result = Subject.GetItems().Single();
result.Status.Should().Be(DownloadItemStatus.Warning);
}
[TestCase("1.0", false)]
[TestCase("2.2", false)]
[TestCase("2.3", true)]
[TestCase("2.4", true)]
[TestCase("3.0", true)]
public void should_test_api_version(string version, bool expected)
{
Mocker.GetMock<INzbVortexProxy>()
.Setup(v => v.GetGroups(It.IsAny<NzbVortexSettings>()))
.Returns(new List<NzbVortexGroup> { new NzbVortexGroup { GroupName = ((NzbVortexSettings)Subject.Definition.Settings).TvCategory } });
Mocker.GetMock<INzbVortexProxy>()
.Setup(v => v.GetApiVersion(It.IsAny<NzbVortexSettings>()))
.Returns(new NzbVortexApiVersionResponse { ApiLevel = version });
var error = Subject.Test();
error.IsValid.Should().Be(expected);
}
}
}

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