From 11c49c9260c38b2c61eeee25348e14b9cf66bfe2 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Fri, 23 Aug 2013 19:21:12 -0700 Subject: [PATCH 01/58] Using services to get updates now --- NzbDrone.Common/NzbDrone.Common.csproj | 1 + NzbDrone.Common/Serializer/Json.cs | 3 -- NzbDrone.Common/Services.cs | 18 ++++++++ .../Scene/SceneMappingProxyFixture.cs | 8 ---- .../UpdatePackageProviderFixture.cs | 8 +--- NzbDrone.Core/Configuration/ConfigService.cs | 5 --- NzbDrone.Core/Configuration/IConfigService.cs | 1 - .../DailySeries/DailySeriesDataProxy.cs | 8 ++-- .../Scene/SceneMappingProxy.cs | 8 +--- NzbDrone.Core/NzbDrone.Core.csproj | 1 + NzbDrone.Core/Update/UpdateCheckService.cs | 2 +- NzbDrone.Core/Update/UpdatePackage.cs | 11 ++++- .../Update/UpdatePackageAvailable.cs | 13 ++++++ NzbDrone.Core/Update/UpdatePackageProvider.cs | 45 +++++-------------- 14 files changed, 59 insertions(+), 73 deletions(-) create mode 100644 NzbDrone.Common/Services.cs create mode 100644 NzbDrone.Core/Update/UpdatePackageAvailable.cs diff --git a/NzbDrone.Common/NzbDrone.Common.csproj b/NzbDrone.Common/NzbDrone.Common.csproj index 42d7d09034..c1b17236fa 100644 --- a/NzbDrone.Common/NzbDrone.Common.csproj +++ b/NzbDrone.Common/NzbDrone.Common.csproj @@ -93,6 +93,7 @@ + diff --git a/NzbDrone.Common/Serializer/Json.cs b/NzbDrone.Common/Serializer/Json.cs index 59c58946ac..866776ec9f 100644 --- a/NzbDrone.Common/Serializer/Json.cs +++ b/NzbDrone.Common/Serializer/Json.cs @@ -40,7 +40,6 @@ public static string ToJson(this object obj) return JsonConvert.SerializeObject(obj); } - public static void Serialize(TModel model, TextWriter outputStream) { var jsonTextWriter = new JsonTextWriter(outputStream); @@ -52,7 +51,5 @@ public static void Serialize(TModel model, Stream outputStream) { Serialize(model, new StreamWriter(outputStream)); } - - } } \ No newline at end of file diff --git a/NzbDrone.Common/Services.cs b/NzbDrone.Common/Services.cs new file mode 100644 index 0000000000..bfa5379019 --- /dev/null +++ b/NzbDrone.Common/Services.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace NzbDrone.Common +{ + public class Services + { + public static String RootUrl + { + get + { + return "http://services.nzbdrone.com"; + } + } + } +} diff --git a/NzbDrone.Core.Test/DataAugmentationFixture/Scene/SceneMappingProxyFixture.cs b/NzbDrone.Core.Test/DataAugmentationFixture/Scene/SceneMappingProxyFixture.cs index 64c5cbc793..98ad8b5042 100644 --- a/NzbDrone.Core.Test/DataAugmentationFixture/Scene/SceneMappingProxyFixture.cs +++ b/NzbDrone.Core.Test/DataAugmentationFixture/Scene/SceneMappingProxyFixture.cs @@ -15,14 +15,6 @@ public class SceneMappingProxyFixture : CoreTest { private const string SCENE_MAPPING_URL = "http://services.nzbdrone.com/SceneMapping/Active"; - [SetUp] - public void Setup() - { - Mocker.GetMock().SetupGet(s => s.ServiceRootUrl) - .Returns("http://services.nzbdrone.com"); - - } - [Test] public void fetch_should_return_list_of_mappings() { diff --git a/NzbDrone.Core.Test/UpdateTests/UpdatePackageProviderFixture.cs b/NzbDrone.Core.Test/UpdateTests/UpdatePackageProviderFixture.cs index bbf0c5b9c8..138e3b404c 100644 --- a/NzbDrone.Core.Test/UpdateTests/UpdatePackageProviderFixture.cs +++ b/NzbDrone.Core.Test/UpdateTests/UpdatePackageProviderFixture.cs @@ -16,13 +16,7 @@ public void should_get_list_of_available_updates() Mocker.GetMock().SetupGet(c => c.Branch).Returns("master"); - var updates = Subject.GetAvailablePackages().ToList(); - - updates.Should().NotBeEmpty(); - updates.Should().OnlyContain(c => !string.IsNullOrWhiteSpace(c.FileName)); - updates.Should().OnlyContain(c => !string.IsNullOrWhiteSpace(c.Url)); - updates.Should().OnlyContain(c => c.Version != null); - updates.Should().OnlyContain(c => c.Version.Major == 2); + Subject.GetLatestUpdate().Should().BeNull(); } } } diff --git a/NzbDrone.Core/Configuration/ConfigService.cs b/NzbDrone.Core/Configuration/ConfigService.cs index 0d9189fc61..e3ca0317bf 100644 --- a/NzbDrone.Core/Configuration/ConfigService.cs +++ b/NzbDrone.Core/Configuration/ConfigService.cs @@ -172,11 +172,6 @@ public string BlackholeFolder set { SetValue("BlackholeFolder", value); } } - public string ServiceRootUrl - { - get { return "http://services.nzbdrone.com"; } - } - public string PneumaticFolder { get { return GetValue("PneumaticFolder", String.Empty); } diff --git a/NzbDrone.Core/Configuration/IConfigService.cs b/NzbDrone.Core/Configuration/IConfigService.cs index 07e70d25b0..d84ed272be 100644 --- a/NzbDrone.Core/Configuration/IConfigService.cs +++ b/NzbDrone.Core/Configuration/IConfigService.cs @@ -25,7 +25,6 @@ public interface IConfigService int Retention { get; set; } DownloadClientType DownloadClient { get; set; } string BlackholeFolder { get; set; } - string ServiceRootUrl { get; } string PneumaticFolder { get; set; } string RecycleBin { get; set; } String NzbgetUsername { get; set; } diff --git a/NzbDrone.Core/DataAugmentation/DailySeries/DailySeriesDataProxy.cs b/NzbDrone.Core/DataAugmentation/DailySeries/DailySeriesDataProxy.cs index fc2a591a27..239afecc81 100644 --- a/NzbDrone.Core/DataAugmentation/DailySeries/DailySeriesDataProxy.cs +++ b/NzbDrone.Core/DataAugmentation/DailySeries/DailySeriesDataProxy.cs @@ -17,13 +17,11 @@ public interface IDailySeriesDataProxy public class DailySeriesDataProxy : IDailySeriesDataProxy { private readonly IHttpProvider _httpProvider; - private readonly IConfigService _configService; private readonly Logger _logger; - public DailySeriesDataProxy(IHttpProvider httpProvider, IConfigService configService, Logger logger) + public DailySeriesDataProxy(IHttpProvider httpProvider, Logger logger) { _httpProvider = httpProvider; - _configService = configService; _logger = logger; } @@ -31,7 +29,7 @@ public IEnumerable GetDailySeriesIds() { try { - var dailySeriesIds = _httpProvider.DownloadString(_configService.ServiceRootUrl + "/DailySeries/AllIds"); + var dailySeriesIds = _httpProvider.DownloadString(Services.RootUrl + "/DailySeries/AllIds"); var seriesIds = Json.Deserialize>(dailySeriesIds); @@ -49,7 +47,7 @@ public bool IsDailySeries(int tvdbid) { try { - var result = _httpProvider.DownloadString(_configService.ServiceRootUrl + "/DailySeries/Check?seriesId=" + tvdbid); + var result = _httpProvider.DownloadString(Services.RootUrl + "/DailySeries/Check?seriesId=" + tvdbid); return Convert.ToBoolean(result); } catch (Exception ex) diff --git a/NzbDrone.Core/DataAugmentation/Scene/SceneMappingProxy.cs b/NzbDrone.Core/DataAugmentation/Scene/SceneMappingProxy.cs index c38cb4a58f..2447a96ec7 100644 --- a/NzbDrone.Core/DataAugmentation/Scene/SceneMappingProxy.cs +++ b/NzbDrone.Core/DataAugmentation/Scene/SceneMappingProxy.cs @@ -13,19 +13,15 @@ public interface ISceneMappingProxy public class SceneMappingProxy : ISceneMappingProxy { private readonly IHttpProvider _httpProvider; - private readonly IConfigService _configService; - - public SceneMappingProxy(IHttpProvider httpProvider, IConfigService configService) + public SceneMappingProxy(IHttpProvider httpProvider) { _httpProvider = httpProvider; - _configService = configService; - } public List Fetch() { - var mappingsJson = _httpProvider.DownloadString(_configService.ServiceRootUrl + "/SceneMapping/Active"); + var mappingsJson = _httpProvider.DownloadString(Services.RootUrl + "/SceneMapping/Active"); return Json.Deserialize>(mappingsJson); } } diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index 7adf989f7d..9234720afa 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -492,6 +492,7 @@ + diff --git a/NzbDrone.Core/Update/UpdateCheckService.cs b/NzbDrone.Core/Update/UpdateCheckService.cs index 36d43ea440..313f1ef58d 100644 --- a/NzbDrone.Core/Update/UpdateCheckService.cs +++ b/NzbDrone.Core/Update/UpdateCheckService.cs @@ -26,7 +26,7 @@ public UpdatePackage AvailableUpdate() { var latestAvailable = _updatePackageProvider.GetLatestUpdate(); - if (latestAvailable == null || latestAvailable.Version <= BuildInfo.Version) + if (latestAvailable == null) { _logger.Debug("No update available."); return null; diff --git a/NzbDrone.Core/Update/UpdatePackage.cs b/NzbDrone.Core/Update/UpdatePackage.cs index e600e2a830..ce038ac999 100644 --- a/NzbDrone.Core/Update/UpdatePackage.cs +++ b/NzbDrone.Core/Update/UpdatePackage.cs @@ -1,11 +1,18 @@ using System; +using Newtonsoft.Json; namespace NzbDrone.Core.Update { public class UpdatePackage { - public string Url { get; set; } - public string FileName { get; set; } + public String Id { get; set; } + + [JsonConverter(typeof(Newtonsoft.Json.Converters.VersionConverter))] public Version Version { get; set; } + + public String Branch { get; set; } + public DateTime ReleaseDate { get; set; } + public String FileName { get; set; } + public String Url { get; set; } } } diff --git a/NzbDrone.Core/Update/UpdatePackageAvailable.cs b/NzbDrone.Core/Update/UpdatePackageAvailable.cs new file mode 100644 index 0000000000..1d76e22d70 --- /dev/null +++ b/NzbDrone.Core/Update/UpdatePackageAvailable.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace NzbDrone.Core.Update +{ + public class UpdatePackageAvailable + { + public Boolean Available { get; set; } + public UpdatePackage UpdatePackage { get; set; } + } +} diff --git a/NzbDrone.Core/Update/UpdatePackageProvider.cs b/NzbDrone.Core/Update/UpdatePackageProvider.cs index f85dc6e66f..2456b55118 100644 --- a/NzbDrone.Core/Update/UpdatePackageProvider.cs +++ b/NzbDrone.Core/Update/UpdatePackageProvider.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; +using Newtonsoft.Json; using NLog; using NzbDrone.Common; using NzbDrone.Common.EnvironmentInfo; @@ -11,56 +12,30 @@ namespace NzbDrone.Core.Update { public interface IUpdatePackageProvider { - IEnumerable GetAvailablePackages(); UpdatePackage GetLatestUpdate(); } public class UpdatePackageProvider : IUpdatePackageProvider { - private readonly IConfigFileProvider _configService; + private readonly IConfigFileProvider _configFileProvider; private readonly IHttpProvider _httpProvider; private readonly Logger _logger; - private static readonly Regex ParseRegex = new Regex(@"(?:\>)(?NzbDrone.+?(?(?<=\.)\d+\.\d+\.\d+\.\d+).+?)(?:\<\/a\>)", - RegexOptions.IgnoreCase); - - public UpdatePackageProvider(IConfigFileProvider configService, IHttpProvider httpProvider, Logger logger) + public UpdatePackageProvider(IConfigFileProvider configFileProvider, IHttpProvider httpProvider, Logger logger) { - _configService = configService; + _configFileProvider = configFileProvider; _httpProvider = httpProvider; _logger = logger; } - public IEnumerable GetAvailablePackages() - { - var updateList = new List(); - - var branch = _configService.Branch; - var version = BuildInfo.Version; - var updateUrl = String.Format("http://update.nzbdrone.com/v{0}/{1}/", version.Major, branch); - - _logger.Debug("Getting a list of updates from {0}", updateUrl); - - var rawUpdateList = _httpProvider.DownloadString(updateUrl); - var matches = ParseRegex.Matches(rawUpdateList); - - foreach (Match match in matches) - { - var updatePackage = new UpdatePackage(); - updatePackage.FileName = match.Groups["filename"].Value; - updatePackage.Url = updateUrl + updatePackage.FileName; - updatePackage.Version = new Version(match.Groups["version"].Value); - updateList.Add(updatePackage); - } - - _logger.Debug("Found {0} update packages", updateUrl.Length); - - return updateList; - } - public UpdatePackage GetLatestUpdate() { - return GetAvailablePackages().OrderByDescending(c => c.Version).FirstOrDefault(); + var url = String.Format("{0}/v1/update/{1}?{2}", Services.RootUrl, _configFileProvider.Branch, BuildInfo.Version); + var update = JsonConvert.DeserializeObject(_httpProvider.DownloadString(url)); + + if (!update.Available) return null; + + return update.UpdatePackage; } } } \ No newline at end of file From c6bbc52631cf807682fa74362310005fb8582630 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Fri, 23 Aug 2013 19:42:45 -0700 Subject: [PATCH 02/58] Fixed UpdateResource --- NzbDrone.Api/Update/UpdateModule.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/NzbDrone.Api/Update/UpdateModule.cs b/NzbDrone.Api/Update/UpdateModule.cs index 6fdb1ca50e..8a95efa4b2 100644 --- a/NzbDrone.Api/Update/UpdateModule.cs +++ b/NzbDrone.Api/Update/UpdateModule.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Newtonsoft.Json; using NzbDrone.Api.REST; using NzbDrone.Core.Update; using NzbDrone.Api.Mapping; @@ -32,7 +33,13 @@ private List GetAvailableUpdate() public class UpdateResource : RestResource { + public String Id { get; set; } + + [JsonConverter(typeof(Newtonsoft.Json.Converters.VersionConverter))] public Version Version { get; set; } + + public String Branch { get; set; } + public DateTime ReleaseDate { get; set; } public String FileName { get; set; } public String Url { get; set; } } From eefe44caa50b9ffb83b4f0e67a3e479316023204 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Fri, 23 Aug 2013 19:45:59 -0700 Subject: [PATCH 03/58] added version to query string --- NzbDrone.Core/Update/UpdatePackageProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NzbDrone.Core/Update/UpdatePackageProvider.cs b/NzbDrone.Core/Update/UpdatePackageProvider.cs index 2456b55118..e045a89fd2 100644 --- a/NzbDrone.Core/Update/UpdatePackageProvider.cs +++ b/NzbDrone.Core/Update/UpdatePackageProvider.cs @@ -30,7 +30,7 @@ public UpdatePackageProvider(IConfigFileProvider configFileProvider, IHttpProvid public UpdatePackage GetLatestUpdate() { - var url = String.Format("{0}/v1/update/{1}?{2}", Services.RootUrl, _configFileProvider.Branch, BuildInfo.Version); + var url = String.Format("{0}/v1/update/{1}?version={2}", Services.RootUrl, _configFileProvider.Branch, BuildInfo.Version); var update = JsonConvert.DeserializeObject(_httpProvider.DownloadString(url)); if (!update.Available) return null; From 2a11d6bf31a0954fb5cab3d513a9662a3743381b Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Mon, 26 Aug 2013 13:05:13 -0700 Subject: [PATCH 04/58] Cache list of Xem Mapped series at start and recache every 12 hours --- NzbDrone.Core/Providers/XemProvider.cs | 46 +++++++++++++++++++++----- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/NzbDrone.Core/Providers/XemProvider.cs b/NzbDrone.Core/Providers/XemProvider.cs index 0881f4edc4..931793dfb6 100644 --- a/NzbDrone.Core/Providers/XemProvider.cs +++ b/NzbDrone.Core/Providers/XemProvider.cs @@ -2,7 +2,9 @@ using System.Collections.Generic; using System.Linq; using NLog; +using NzbDrone.Common.Cache; using NzbDrone.Common.Messaging; +using NzbDrone.Core.Lifecycle; using NzbDrone.Core.Tv; using NzbDrone.Core.Tv.Events; @@ -12,31 +14,37 @@ public interface IXemProvider { void UpdateMappings(); void UpdateMappings(int seriesId); + void UpdateMappings(Series series); void PerformUpdate(Series series); } - public class XemProvider : IXemProvider, IExecute, IHandle + public class XemProvider : IXemProvider, IExecute, IHandle, IHandleAsync { private readonly IEpisodeService _episodeService; private readonly IXemCommunicationProvider _xemCommunicationProvider; private readonly ISeriesService _seriesService; + private readonly ICached _cache; private static readonly Logger _logger = LogManager.GetCurrentClassLogger(); - public XemProvider(IEpisodeService episodeService, IXemCommunicationProvider xemCommunicationProvider, ISeriesService seriesService) + public XemProvider(IEpisodeService episodeService, + IXemCommunicationProvider xemCommunicationProvider, + ISeriesService seriesService, ICacheManger cacheManger) { if (seriesService == null) throw new ArgumentNullException("seriesService"); _episodeService = episodeService; _xemCommunicationProvider = xemCommunicationProvider; _seriesService = seriesService; + _cache = cacheManger.GetCache(GetType()); } public void UpdateMappings() { _logger.Trace("Starting scene numbering update"); + try { - var ids = _xemCommunicationProvider.GetXemSeriesIds(); + var ids = GetXemSeriesIds(); var series = _seriesService.GetAllSeries(); var wantedSeries = series.Where(s => ids.Contains(s.TvdbId)).ToList(); @@ -64,12 +72,15 @@ public void UpdateMappings(int seriesId) _logger.Trace("Series could not be found: {0}", seriesId); return; } + + UpdateMappings(series); + } - var xemIds = _xemCommunicationProvider.GetXemSeriesIds(); - - if (!xemIds.Contains(series.TvdbId)) + public void UpdateMappings(Series series) + { + if (!_cache.Find(series.TvdbId.ToString())) { - _logger.Trace("Xem doesn't have a mapping for this series: {0}", series.TvdbId); + _logger.Trace("Scene numbering is not available for {0} [{1}]", series.Title, series.TvdbId); return; } @@ -125,6 +136,20 @@ public void PerformUpdate(Series series) } } + private List GetXemSeriesIds() + { + _cache.Clear(); + + var ids = _xemCommunicationProvider.GetXemSeriesIds(); + + foreach (var id in ids) + { + _cache.Set(id.ToString(), true); + } + + return ids; + } + public void Execute(UpdateXemMappingsCommand message) { if (message.SeriesId.HasValue) @@ -139,7 +164,12 @@ public void Execute(UpdateXemMappingsCommand message) public void Handle(SeriesUpdatedEvent message) { - PerformUpdate(message.Series); + UpdateMappings(message.Series); + } + + public void HandleAsync(ApplicationStartedEvent message) + { + GetXemSeriesIds(); } } } From 6bea671a1a041858eeb27a610c4c7e31155ec3a2 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Mon, 26 Aug 2013 20:20:03 -0700 Subject: [PATCH 05/58] Episode and Season monitored toggling works again --- NzbDrone.Api/Episodes/EpisodeModule.cs | 7 ++ NzbDrone.Api/Seasons/SeasonModule.cs | 7 ++ NzbDrone.Core/Tv/SeasonService.cs | Bin 8428 -> 8572 bytes .../Client/ClientBase.cs | 16 ++++- .../Client/EpisodeClient.cs | 22 +++++++ .../Client/SeasonClient.cs | 22 +++++++ .../EpisodeIntegrationTests.cs | 60 ++++++++++++++++++ NzbDrone.Integration.Test/IntegrationTest.cs | 5 ++ .../NzbDrone.Integration.Test.csproj | 4 ++ .../SeasonIntegrationTests.cs | 60 ++++++++++++++++++ 10 files changed, 200 insertions(+), 3 deletions(-) create mode 100644 NzbDrone.Integration.Test/Client/EpisodeClient.cs create mode 100644 NzbDrone.Integration.Test/Client/SeasonClient.cs create mode 100644 NzbDrone.Integration.Test/EpisodeIntegrationTests.cs create mode 100644 NzbDrone.Integration.Test/SeasonIntegrationTests.cs diff --git a/NzbDrone.Api/Episodes/EpisodeModule.cs b/NzbDrone.Api/Episodes/EpisodeModule.cs index 94874f57a9..3d6684d19f 100644 --- a/NzbDrone.Api/Episodes/EpisodeModule.cs +++ b/NzbDrone.Api/Episodes/EpisodeModule.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using NzbDrone.Api.Mapping; using NzbDrone.Api.REST; using NzbDrone.Core.Tv; @@ -15,6 +16,7 @@ public EpisodeModule(IEpisodeService episodeService) GetResourceAll = GetEpisodes; UpdateResource = SetMonitored; + GetResourceById = GetEpisode; } private List GetEpisodes() @@ -33,5 +35,10 @@ private void SetMonitored(EpisodeResource episodeResource) { _episodeService.SetEpisodeMonitored(episodeResource.Id, episodeResource.Monitored); } + + private EpisodeResource GetEpisode(int id) + { + return _episodeService.GetEpisode(id).InjectTo(); + } } } \ No newline at end of file diff --git a/NzbDrone.Api/Seasons/SeasonModule.cs b/NzbDrone.Api/Seasons/SeasonModule.cs index 8c6bf7d8b1..0521b85186 100644 --- a/NzbDrone.Api/Seasons/SeasonModule.cs +++ b/NzbDrone.Api/Seasons/SeasonModule.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using NzbDrone.Api.Mapping; using NzbDrone.Core.Tv; namespace NzbDrone.Api.Seasons @@ -13,6 +14,7 @@ public SeasonModule(ISeasonService seasonService) _seasonService = seasonService; GetResourceAll = GetSeasons; + GetResourceById = GetSeason; UpdateResource = Update; Post["/pass"] = x => SetSeasonPass(); @@ -30,6 +32,11 @@ private List GetSeasons() return ToListResource(() => _seasonService.GetAllSeasons()); } + private SeasonResource GetSeason(int id) + { + return _seasonService.Get(id).InjectTo(); + } + private void Update(SeasonResource seasonResource) { _seasonService.SetMonitored(seasonResource.SeriesId, seasonResource.SeasonNumber, seasonResource.Monitored); diff --git a/NzbDrone.Core/Tv/SeasonService.cs b/NzbDrone.Core/Tv/SeasonService.cs index de0c4013de8646ad2eb640d4dfc6fca885572538..8cb3d0c75795638537f01c86fdb483b545701f5e 100644 GIT binary patch delta 108 zcmaFk_{WLAv^X;_T_L!#xFj{#nwM+CZ$?oCAP7!PEY8nUa8E7K$jmEI$V}P%nX!av t@&z7|&9y8^9D*3~lk0hm*}%$ECOhz&Z~n%k&B|E2*-&UV-(&|NZU8dtB+mc< delta 46 zcmV+}0MY;aLhM1Y5BmYLCjx8&lj98*v!?`N2$S>;7qf~DD+L7&3JnT(request); } + public TResource Put(TResource body) + { + var request = BuildRequest(); + request.AddBody(body); + return Put(request); + } + public TResource Get(int id, HttpStatusCode statusCode = HttpStatusCode.OK) { var request = BuildRequest(id.ToString()); return Get(request, statusCode); } - public void Delete(int id) { var request = BuildRequest(id.ToString()); @@ -82,6 +88,12 @@ protected RestRequest BuildRequest(string command = "") return Execute(request, statusCode); } + public T Put(IRestRequest request, HttpStatusCode statusCode = HttpStatusCode.Accepted) where T : class, new() + { + request.Method = Method.PUT; + return Execute(request, statusCode); + } + public void Delete(IRestRequest request, HttpStatusCode statusCode = HttpStatusCode.OK) { request.Method = Method.DELETE; @@ -109,13 +121,11 @@ public void Delete(IRestRequest request, HttpStatusCode statusCode = HttpStatusC return Json.Deserialize(response.Content); } - private static void AssertDisableCache(IList headers) { headers.Single(c => c.Name == "Cache-Control").Value.Should().Be("no-cache, no-store, must-revalidate"); headers.Single(c => c.Name == "Pragma").Value.Should().Be("no-cache"); headers.Single(c => c.Name == "Expires").Value.Should().Be("0"); } - } } \ No newline at end of file diff --git a/NzbDrone.Integration.Test/Client/EpisodeClient.cs b/NzbDrone.Integration.Test/Client/EpisodeClient.cs new file mode 100644 index 0000000000..675c38bd8b --- /dev/null +++ b/NzbDrone.Integration.Test/Client/EpisodeClient.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using System.Net; +using NzbDrone.Api.Episodes; +using NzbDrone.Api.Series; +using RestSharp; + +namespace NzbDrone.Integration.Test.Client +{ + public class EpisodeClient : ClientBase + { + public EpisodeClient(IRestClient restClient) + : base(restClient, "episodes") + { + } + + public List GetEpisodesInSeries(int seriesId) + { + var request = BuildRequest("?seriesId=" + seriesId.ToString()); + return Get>(request); + } + } +} diff --git a/NzbDrone.Integration.Test/Client/SeasonClient.cs b/NzbDrone.Integration.Test/Client/SeasonClient.cs new file mode 100644 index 0000000000..af0572a703 --- /dev/null +++ b/NzbDrone.Integration.Test/Client/SeasonClient.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using System.Net; +using NzbDrone.Api.Episodes; +using NzbDrone.Api.Seasons; +using RestSharp; + +namespace NzbDrone.Integration.Test.Client +{ + public class SeasonClient : ClientBase + { + public SeasonClient(IRestClient restClient) + : base(restClient) + { + } + + public List GetSeasonsInSeries(int seriesId) + { + var request = BuildRequest("?seriesId=" + seriesId.ToString()); + return Get>(request); + } + } +} diff --git a/NzbDrone.Integration.Test/EpisodeIntegrationTests.cs b/NzbDrone.Integration.Test/EpisodeIntegrationTests.cs new file mode 100644 index 0000000000..411023cacb --- /dev/null +++ b/NzbDrone.Integration.Test/EpisodeIntegrationTests.cs @@ -0,0 +1,60 @@ +using System; +using System.Threading; +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Api.Series; +using System.Linq; + +namespace NzbDrone.Integration.Test +{ + [TestFixture] + public class EpisodeIntegrationTests : IntegrationTest + { + private SeriesResource GivenSeriesWithEpisodes() + { + var series = Series.Lookup("archer").First(); + + series.QualityProfileId = 1; + series.Path = @"C:\Test\Archer"; + + series = Series.Post(series); + + while (true) + { + if (Episodes.GetEpisodesInSeries(series.Id).Count > 0) + { + return series; + } + + Thread.Sleep(1000); + } + } + + [Test] + public void should_be_able_to_get_all_episodes_in_series() + { + var series = GivenSeriesWithEpisodes(); + Episodes.GetEpisodesInSeries(series.Id).Count.Should().BeGreaterThan(0); + } + + [Test] + public void should_be_able_to_get_a_single_episode() + { + var series = GivenSeriesWithEpisodes(); + var episodes = Episodes.GetEpisodesInSeries(series.Id); + + Episodes.Get(episodes.First().Id).Should().NotBeNull(); + } + + [Test] + public void should_be_able_to_set_monitor_status_via_api() + { + var series = GivenSeriesWithEpisodes(); + var episodes = Episodes.GetEpisodesInSeries(series.Id); + var updatedEpisode = episodes.First(); + updatedEpisode.Monitored = false; + + Episodes.Put(updatedEpisode).Monitored.Should().BeFalse(); + } + } +} \ No newline at end of file diff --git a/NzbDrone.Integration.Test/IntegrationTest.cs b/NzbDrone.Integration.Test/IntegrationTest.cs index 313e58f5ba..b705146b65 100644 --- a/NzbDrone.Integration.Test/IntegrationTest.cs +++ b/NzbDrone.Integration.Test/IntegrationTest.cs @@ -3,6 +3,7 @@ using NLog.Targets; using NUnit.Framework; using NzbDrone.Api.Commands; +using NzbDrone.Api.Episodes; using NzbDrone.Api.RootFolders; using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Integration.Test.Client; @@ -22,6 +23,8 @@ public abstract class IntegrationTest protected ClientBase Commands; protected ReleaseClient Releases; protected IndexerClient Indexers; + protected EpisodeClient Episodes; + protected SeasonClient Seasons; private NzbDroneRunner _runner; @@ -57,6 +60,8 @@ private void InitRestClients() RootFolders = new ClientBase(RestClient); Commands = new ClientBase(RestClient); Indexers = new IndexerClient(RestClient); + Episodes = new EpisodeClient(RestClient); + Seasons = new SeasonClient(RestClient); } [TearDown] diff --git a/NzbDrone.Integration.Test/NzbDrone.Integration.Test.csproj b/NzbDrone.Integration.Test/NzbDrone.Integration.Test.csproj index a3d18d2b58..04ce2753cd 100644 --- a/NzbDrone.Integration.Test/NzbDrone.Integration.Test.csproj +++ b/NzbDrone.Integration.Test/NzbDrone.Integration.Test.csproj @@ -93,10 +93,14 @@ + + + + diff --git a/NzbDrone.Integration.Test/SeasonIntegrationTests.cs b/NzbDrone.Integration.Test/SeasonIntegrationTests.cs new file mode 100644 index 0000000000..c101460309 --- /dev/null +++ b/NzbDrone.Integration.Test/SeasonIntegrationTests.cs @@ -0,0 +1,60 @@ +using System; +using System.Threading; +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Api.Series; +using System.Linq; + +namespace NzbDrone.Integration.Test +{ + [TestFixture] + public class SeasonIntegrationTests : IntegrationTest + { + private SeriesResource GivenSeriesWithEpisodes() + { + var series = Series.Lookup("archer").First(); + + series.QualityProfileId = 1; + series.Path = @"C:\Test\Archer"; + + series = Series.Post(series); + + while (true) + { + if (Seasons.GetSeasonsInSeries(series.Id).Count > 0) + { + return series; + } + + Thread.Sleep(1000); + } + } + + [Test] + public void should_be_able_to_get_all_seasons_in_series() + { + var series = GivenSeriesWithEpisodes(); + Seasons.GetSeasonsInSeries(series.Id).Count.Should().BeGreaterThan(0); + } + + [Test] + public void should_be_able_to_get_a_single_season() + { + var series = GivenSeriesWithEpisodes(); + var seasons = Seasons.GetSeasonsInSeries(series.Id); + + Seasons.Get(seasons.First().Id).Should().NotBeNull(); + } + + [Test] + public void should_be_able_to_set_monitor_status_via_api() + { + var series = GivenSeriesWithEpisodes(); + var seasons = Seasons.GetSeasonsInSeries(series.Id); + var updatedSeason = seasons.First(); + updatedSeason.Monitored = false; + + Seasons.Put(updatedSeason).Monitored.Should().BeFalse(); + } + } +} \ No newline at end of file From 0d4fc5513a6dcdbc1b9a458dd1aeb6c2995fa2b6 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Mon, 26 Aug 2013 22:16:22 -0700 Subject: [PATCH 06/58] Using OsAgnostic paths for episode/season integration tests --- NzbDrone.Integration.Test/EpisodeIntegrationTests.cs | 3 ++- NzbDrone.Integration.Test/SeasonIntegrationTests.cs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/NzbDrone.Integration.Test/EpisodeIntegrationTests.cs b/NzbDrone.Integration.Test/EpisodeIntegrationTests.cs index 411023cacb..d0f74844df 100644 --- a/NzbDrone.Integration.Test/EpisodeIntegrationTests.cs +++ b/NzbDrone.Integration.Test/EpisodeIntegrationTests.cs @@ -4,6 +4,7 @@ using NUnit.Framework; using NzbDrone.Api.Series; using System.Linq; +using NzbDrone.Test.Common; namespace NzbDrone.Integration.Test { @@ -15,7 +16,7 @@ private SeriesResource GivenSeriesWithEpisodes() var series = Series.Lookup("archer").First(); series.QualityProfileId = 1; - series.Path = @"C:\Test\Archer"; + series.Path = @"C:\Test\Archer".AsOsAgnostic(); series = Series.Post(series); diff --git a/NzbDrone.Integration.Test/SeasonIntegrationTests.cs b/NzbDrone.Integration.Test/SeasonIntegrationTests.cs index c101460309..9fa6177f36 100644 --- a/NzbDrone.Integration.Test/SeasonIntegrationTests.cs +++ b/NzbDrone.Integration.Test/SeasonIntegrationTests.cs @@ -4,6 +4,7 @@ using NUnit.Framework; using NzbDrone.Api.Series; using System.Linq; +using NzbDrone.Test.Common; namespace NzbDrone.Integration.Test { @@ -15,7 +16,7 @@ private SeriesResource GivenSeriesWithEpisodes() var series = Series.Lookup("archer").First(); series.QualityProfileId = 1; - series.Path = @"C:\Test\Archer"; + series.Path = @"C:\Test\Archer".AsOsAgnostic(); series = Series.Post(series); From dcb1b76917a72f934c03c968c3e84bdae8277cfd Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Mon, 26 Aug 2013 22:20:08 -0700 Subject: [PATCH 07/58] Added spaces so the split works --- NzbDrone.Core/MediaFiles/DiskScanService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NzbDrone.Core/MediaFiles/DiskScanService.cs b/NzbDrone.Core/MediaFiles/DiskScanService.cs index 17d7e6dc2c..0fb6901fe8 100644 --- a/NzbDrone.Core/MediaFiles/DiskScanService.cs +++ b/NzbDrone.Core/MediaFiles/DiskScanService.cs @@ -24,9 +24,9 @@ public class DiskScanService : private const string EXTENSIONS = //XBMC - ".m4v .3gp .nsv .ts .ty .strm .rm .rmvb .m3u .ifo .mov .qt .divx .xvid .bivx .vob .nrg .img" + + ".m4v .3gp .nsv .ts .ty .strm .rm .rmvb .m3u .ifo .mov .qt .divx .xvid .bivx .vob .nrg .img " + ".iso .pva .wmv .asf .asx .ogm .m2v .avi .bin .dat .dvr-ms .mpg .mpeg .mp4 .mkv .avc .vp3 " + - ".svq3 .nuv .viv .dv .fli .flv .wpl" + + ".svq3 .nuv .viv .dv .fli .flv .wpl " + //Other ".m2ts"; From 3c732f5a5e847f6c4b7ca76e645e9e6445ab2cbf Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Tue, 27 Aug 2013 07:08:00 -0700 Subject: [PATCH 08/58] 1080p releases without x264 or hdtv markers will be treated as HDTV instead of unknown --- NzbDrone.Core.Test/ParserTests/QualityParserFixture.cs | 3 ++- NzbDrone.Core/Parser/Parser.cs | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/NzbDrone.Core.Test/ParserTests/QualityParserFixture.cs b/NzbDrone.Core.Test/ParserTests/QualityParserFixture.cs index 7f433c41ea..e2704d1868 100644 --- a/NzbDrone.Core.Test/ParserTests/QualityParserFixture.cs +++ b/NzbDrone.Core.Test/ParserTests/QualityParserFixture.cs @@ -79,7 +79,8 @@ public class QualityParserFixture : CoreTest new object[] { "How I Met Your Mother S01E18 Nothing Good Happens After 2 A.M. 720p HDTV DD5.1 MPEG2-TrollHD", Quality.RAWHD, false }, new object[] { "Arrested.Development.S04E01.iNTERNAL.1080p.WEBRip.x264-QRUS", Quality.WEBDL1080p, false }, new object[] { "Arrested.Development.S04E01.720p.WEBRip.AAC2.0.x264-NFRiP", Quality.WEBDL720p, false }, - new object[] { "Sons.Of.Anarchy.S02E13.1080p.BluRay.x264-AVCDVD", Quality.Bluray1080p, false } + new object[] { "Sons.Of.Anarchy.S02E13.1080p.BluRay.x264-AVCDVD", Quality.Bluray1080p, false }, + new object[] { "Under the Dome S01E10 Let the Games Begin 1080p", Quality.HDTV1080p, false } }; public static object[] SelfQualityParserCases = diff --git a/NzbDrone.Core/Parser/Parser.cs b/NzbDrone.Core/Parser/Parser.cs index 2f88fe81e4..15110894ba 100644 --- a/NzbDrone.Core/Parser/Parser.cs +++ b/NzbDrone.Core/Parser/Parser.cs @@ -386,6 +386,12 @@ private static QualityModel ParseQuality(string name) return result; } + if (normalizedName.Contains("1080p")) + { + result.Quality = Quality.HDTV1080p; + return result; + } + return result; } From e7b329a618fd0b673042567433de594ee103dce0 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Tue, 27 Aug 2013 07:22:14 -0700 Subject: [PATCH 09/58] favicon.ico is now served properly --- NzbDrone.Api/Frontend/Mappers/StaticResourceMapper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NzbDrone.Api/Frontend/Mappers/StaticResourceMapper.cs b/NzbDrone.Api/Frontend/Mappers/StaticResourceMapper.cs index b97f639436..da9fac5322 100644 --- a/NzbDrone.Api/Frontend/Mappers/StaticResourceMapper.cs +++ b/NzbDrone.Api/Frontend/Mappers/StaticResourceMapper.cs @@ -25,7 +25,7 @@ protected override string Map(string resourceUrl) public override bool CanHandle(string resourceUrl) { - return resourceUrl.StartsWith("/Content") || resourceUrl.EndsWith(".js") || resourceUrl.EndsWith(".css"); + return resourceUrl.StartsWith("/Content") || resourceUrl.EndsWith(".js") || resourceUrl.EndsWith(".css") || resourceUrl.EndsWith(".ico"); } } } \ No newline at end of file From 0d6b9969d25f8748b840132d4dd63d623be45dc2 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Tue, 27 Aug 2013 12:13:11 -0700 Subject: [PATCH 10/58] FilterExistingFiles no longer converts paths to all lower case --- NzbDrone.Common/PathEqualityComparer.cs | 8 +++- .../MediaFileTests/MediaFileServiceTest.cs | 44 +++++++++++++++++-- NzbDrone.Core/MediaFiles/MediaFileService.cs | 4 +- 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/NzbDrone.Common/PathEqualityComparer.cs b/NzbDrone.Common/PathEqualityComparer.cs index c70abb7b70..2bf8547277 100644 --- a/NzbDrone.Common/PathEqualityComparer.cs +++ b/NzbDrone.Common/PathEqualityComparer.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using NzbDrone.Common.EnvironmentInfo; namespace NzbDrone.Common { @@ -14,7 +15,12 @@ public bool Equals(string x, string y) public int GetHashCode(string obj) { - return obj.CleanFilePath().GetHashCode(); + if (OsInfo.IsLinux) + { + return obj.CleanFilePath().GetHashCode(); + } + + return obj.CleanFilePath().ToLower().GetHashCode(); } } } diff --git a/NzbDrone.Core.Test/MediaFileTests/MediaFileServiceTest.cs b/NzbDrone.Core.Test/MediaFileTests/MediaFileServiceTest.cs index c97082e3d8..1e1060239d 100644 --- a/NzbDrone.Core.Test/MediaFileTests/MediaFileServiceTest.cs +++ b/NzbDrone.Core.Test/MediaFileTests/MediaFileServiceTest.cs @@ -81,12 +81,11 @@ public void filter_should_return_none_existing_files() Subject.FilterExistingFiles(files, 10).Should().NotContain("c:\\file2.avi".AsOsAgnostic()); } - - - [Test] public void filter_should_return_none_existing_files_ignoring_case() { + WindowsOnly(); + var files = new List() { "c:\\file1.avi".AsOsAgnostic(), @@ -105,5 +104,44 @@ public void filter_should_return_none_existing_files_ignoring_case() Subject.FilterExistingFiles(files, 10).Should().HaveCount(2); Subject.FilterExistingFiles(files, 10).Should().NotContain("c:\\file2.avi".AsOsAgnostic()); } + + [Test] + public void filter_should_return_none_existing_files_not_ignoring_case() + { + LinuxOnly(); + + var files = new List() + { + "c:\\file1.avi".AsOsAgnostic(), + "c:\\FILE2.avi".AsOsAgnostic(), + "c:\\file3.avi".AsOsAgnostic() + }; + + Mocker.GetMock() + .Setup(c => c.GetFilesBySeries(It.IsAny())) + .Returns(new List + { + new EpisodeFile{Path = "c:\\file2.avi".AsOsAgnostic()} + }); + + Subject.FilterExistingFiles(files, 10).Should().HaveCount(3); + } + + [Test] + public void filter_should_not_change_casing() + { + var files = new List() + { + "c:\\FILE1.avi".AsOsAgnostic() + }; + + Mocker.GetMock() + .Setup(c => c.GetFilesBySeries(It.IsAny())) + .Returns(new List()); + + Subject.FilterExistingFiles(files, 10).Should().HaveCount(1); + Subject.FilterExistingFiles(files, 10).Should().NotContain(files.First().ToLower()); + Subject.FilterExistingFiles(files, 10).Should().Contain(files.First()); + } } } \ No newline at end of file diff --git a/NzbDrone.Core/MediaFiles/MediaFileService.cs b/NzbDrone.Core/MediaFiles/MediaFileService.cs index a2fe8ba227..54501c859b 100644 --- a/NzbDrone.Core/MediaFiles/MediaFileService.cs +++ b/NzbDrone.Core/MediaFiles/MediaFileService.cs @@ -76,11 +76,11 @@ public List GetFilesBySeason(int seriesId, int seasonNumber) public List FilterExistingFiles(List files, int seriesId) { - var seriesFiles = GetFilesBySeries(seriesId).Select(f => f.Path.CleanFilePath().ToLower()).ToList(); + var seriesFiles = GetFilesBySeries(seriesId).Select(f => f.Path.CleanFilePath()).ToList(); if (!seriesFiles.Any()) return files; - return files.Select(f => f.CleanFilePath().ToLower()).Except(seriesFiles).ToList(); + return files.Select(f => f.CleanFilePath()).Except(seriesFiles, new PathEqualityComparer()).ToList(); } public EpisodeFile Get(int id) From 8cb8345c3bcf6d9d4ee1d956d154f0b01b8bbf21 Mon Sep 17 00:00:00 2001 From: "kay.one" Date: Tue, 27 Aug 2013 14:31:45 -0700 Subject: [PATCH 11/58] updated deb package files --- debian/changelog | 10 +++++----- debian/control | 14 ++++++-------- debian/copyright | 50 ++++++++++++++++++++++++------------------------ debian/install | 3 +-- debian/rules | 2 +- 5 files changed, 38 insertions(+), 41 deletions(-) mode change 100644 => 100755 debian/copyright mode change 100644 => 100755 debian/install mode change 100644 => 100755 debian/rules diff --git a/debian/changelog b/debian/changelog index e15e9a293c..d19fb36d68 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,5 @@ - nzbdrone (2.0.12-1) unstable; urgency=low -2 -3 * Initial release -4 -5 -- kay.one Mon, 22 Mar 2010 00:37:31 +0100 \ No newline at end of file +nzbdrone (2.0.0.0) UNRELEASED; urgency=low + + * Initial release. (Closes: #XXXXXX) + + -- Keivan Mon, 26 Aug 2013 17:31:17 -0700 diff --git a/debian/control b/debian/control index 174fecb48b..55fdd31fec 100644 --- a/debian/control +++ b/debian/control @@ -1,14 +1,12 @@ -Package: nzbdrone -Standards-Version: 2.0.0.226 -Architecture: all -Maintainer: Keivan Beigi -Depends: mono-runtime (>= 2.10.1) +Source: nzbdrone Section: web Priority: optional - +Maintainer: Keivan Beigi +Depends: libmono-cil-dev (>= 2.10.1) Homepage: http://www.nzbdrone.com Vcs-Git: git@github.com:NzbDrone/NzbDrone.git Vcs-Browser: https://github.com/NzbDrone/NzbDrone -Description: NZBDrone is a PVR for newsgroup users. -It can monitor multiple RSS feeds for new episodes of your favourite shows and will grab, sorts and renames them. It can also be configured to automatically upgrade the quality of files already downloaded if a better quality format becomes available. \ No newline at end of file +Package: nzbdrone +Architecture: all +Description: NZBDrone is a PVR for newsgroup users diff --git a/debian/copyright b/debian/copyright old mode 100644 new mode 100755 index 28e595dc8c..754e0d6392 --- a/debian/copyright +++ b/debian/copyright @@ -1,25 +1,25 @@ -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: nzbdrone -Source: https://github.com/NzbDrone/NzbDrone - -Files: * -Copyright: 2010-2013 Keivan Beigi - 2010-2013 Mark McDowall - -License: GPL-3.0+ - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - . - This package is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - . - You should have received a copy of the GNU General Public License - along with this program. If not, see . - . - On Debian systems, the complete text of the GNU General - Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". \ No newline at end of file +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: nzbdrone +Source: https://github.com/NzbDrone/NzbDrone + +Files: * +Copyright: 2010-2013 Keivan Beigi + 2010-2013 Mark McDowall + +License: GPL-3.0+ + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + . + This package is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + . + You should have received a copy of the GNU General Public License + along with this program. If not, see . + . + On Debian systems, the complete text of the GNU General + Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". diff --git a/debian/install b/debian/install old mode 100644 new mode 100755 index 46a453a03c..c881aacaed --- a/debian/install +++ b/debian/install @@ -1,2 +1 @@ -nzbdrone_226/* opt/nzbdrone -../nzbdrone.desktop usr/share/applications +* opt/NzbDrone diff --git a/debian/rules b/debian/rules old mode 100644 new mode 100755 index fcc2b6104d..b760bee7f4 --- a/debian/rules +++ b/debian/rules @@ -7,7 +7,7 @@ # This special exception was added by Craig Small in version 0.37 of dh-make. # Uncomment this to turn on verbose mode. -export DH_VERBOSE=1 +#export DH_VERBOSE=1 %: dh $@ From 93715ff308a5d422defb0406126d8e98f8be792d Mon Sep 17 00:00:00 2001 From: "kay.one" Date: Tue, 27 Aug 2013 15:08:05 -0700 Subject: [PATCH 12/58] fixed deb install file. --- debian/install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/install b/debian/install index c881aacaed..13f97a3041 100755 --- a/debian/install +++ b/debian/install @@ -1 +1 @@ -* opt/NzbDrone +nzbdrone/* opt/NzbDrone From e25ebf7cd2363221b501749b4dd0b1734a2ea807 Mon Sep 17 00:00:00 2001 From: "kay.one" Date: Tue, 27 Aug 2013 15:29:46 -0700 Subject: [PATCH 13/58] updated compat/install file for debian --- debian/compat | 1 + debian/install | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 debian/compat diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000000..45a4fb75db --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +8 diff --git a/debian/install b/debian/install index 13f97a3041..106b06a9b5 100755 --- a/debian/install +++ b/debian/install @@ -1 +1 @@ -nzbdrone/* opt/NzbDrone +nzbdrone_bin/* opt/NzbDrone From 37d90a34196cfe5a58f5af348b2debf74016896c Mon Sep 17 00:00:00 2001 From: Keivan Beigi Date: Tue, 27 Aug 2013 16:14:10 -0700 Subject: [PATCH 14/58] updated deb maintainer. --- debian/control | 2 +- debian/copyright | 3 +-- debian/files | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) delete mode 100644 debian/files diff --git a/debian/control b/debian/control index 55fdd31fec..ed77723aec 100644 --- a/debian/control +++ b/debian/control @@ -1,7 +1,7 @@ Source: nzbdrone Section: web Priority: optional -Maintainer: Keivan Beigi +Maintainer: NzbDrone Depends: libmono-cil-dev (>= 2.10.1) Homepage: http://www.nzbdrone.com Vcs-Git: git@github.com:NzbDrone/NzbDrone.git diff --git a/debian/copyright b/debian/copyright index 754e0d6392..cf281685c1 100755 --- a/debian/copyright +++ b/debian/copyright @@ -3,8 +3,7 @@ Upstream-Name: nzbdrone Source: https://github.com/NzbDrone/NzbDrone Files: * -Copyright: 2010-2013 Keivan Beigi - 2010-2013 Mark McDowall +Copyright: 2010-2013 NzbDrone License: GPL-3.0+ diff --git a/debian/files b/debian/files deleted file mode 100644 index 5957c8b623..0000000000 --- a/debian/files +++ /dev/null @@ -1 +0,0 @@ -nzbdrone_226_i386.deb unknown extra From 45d0bc0c88ccb9bf7f164f8ab799fc7d448e1018 Mon Sep 17 00:00:00 2001 From: Keivan Beigi Date: Tue, 27 Aug 2013 16:18:22 -0700 Subject: [PATCH 15/58] updated deb changelog --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index d19fb36d68..bacec772a5 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,5 @@ nzbdrone (2.0.0.0) UNRELEASED; urgency=low - * Initial release. (Closes: #XXXXXX) + * Automatic release. - -- Keivan Mon, 26 Aug 2013 17:31:17 -0700 + -- NzbDrone Mon, 26 Aug 2013 12:00:00 -0700 From 1e3a308917699c24581dcf98513dd0e3d8507f50 Mon Sep 17 00:00:00 2001 From: Keivan Beigi Date: Tue, 27 Aug 2013 17:10:52 -0700 Subject: [PATCH 16/58] updated changelog to use token for build and branch --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index bacec772a5..d908f062f4 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,5 @@ -nzbdrone (2.0.0.0) UNRELEASED; urgency=low +nzbdrone {version} {branch}; urgency=low * Automatic release. - -- NzbDrone Mon, 26 Aug 2013 12:00:00 -0700 + -- NzbDrone Mon, 27 Aug 2013 12:00:00 -0700 From dd37713a10bc21d9697e579ceac63d2b39ecf8e6 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Tue, 27 Aug 2013 17:16:24 -0700 Subject: [PATCH 17/58] Naming config fixed, with integration tests --- NzbDrone.Api/Config/NamingModule.cs | 10 ++++-- NzbDrone.Api/NzbDroneRestModule.cs | 2 -- .../Client/ClientBase.cs | 6 ++++ .../CommandIntegerationTests.cs | 2 -- NzbDrone.Integration.Test/IntegrationTest.cs | 7 ++-- .../NamingConfigTests.cs | 35 +++++++++++++++++++ .../NzbDrone.Integration.Test.csproj | 1 + 7 files changed, 52 insertions(+), 11 deletions(-) create mode 100644 NzbDrone.Integration.Test/NamingConfigTests.cs diff --git a/NzbDrone.Api/Config/NamingModule.cs b/NzbDrone.Api/Config/NamingModule.cs index 65f674b49d..726a268b52 100644 --- a/NzbDrone.Api/Config/NamingModule.cs +++ b/NzbDrone.Api/Config/NamingModule.cs @@ -22,10 +22,9 @@ public NamingModule(INamingConfigService namingConfigService, IBuildFileNames bu _namingConfigService = namingConfigService; _buildFileNames = buildFileNames; GetResourceSingle = GetNamingConfig; - + GetResourceById = GetNamingConfig; UpdateResource = UpdateNamingConfig; - Get["/samples"] = x => GetExamples(this.Bind()); SharedValidator.RuleFor(c => c.MultiEpisodeStyle).InclusiveBetween(0, 3); @@ -35,7 +34,7 @@ public NamingModule(INamingConfigService namingConfigService, IBuildFileNames bu private void UpdateNamingConfig(NamingConfigResource resource) { - GetNewId(_namingConfigService.Save, resource); + _namingConfigService.Save(resource.InjectTo()); } private NamingConfigResource GetNamingConfig() @@ -43,6 +42,11 @@ private NamingConfigResource GetNamingConfig() return _namingConfigService.GetConfig().InjectTo(); } + private NamingConfigResource GetNamingConfig(int id) + { + return GetNamingConfig(); + } + private JsonResponse GetExamples(NamingConfigResource config) { var nameSpec = config.InjectTo(); diff --git a/NzbDrone.Api/NzbDroneRestModule.cs b/NzbDrone.Api/NzbDroneRestModule.cs index d8072c4b28..b4b01aee5d 100644 --- a/NzbDrone.Api/NzbDroneRestModule.cs +++ b/NzbDrone.Api/NzbDroneRestModule.cs @@ -21,7 +21,6 @@ protected NzbDroneRestModule(string resource) PutValidator.RuleFor(r => r.Id).ValidId(); } - protected int GetNewId(Func function, TResource resource) where TModel : ModelBase, new() { var model = resource.InjectTo(); @@ -35,7 +34,6 @@ protected NzbDroneRestModule(string resource) return modelList.InjectTo>(); } - protected PagingResource ApplyToPage(Func, PagingSpec> function, PagingSpec pagingSpec) where TModel : ModelBase, new() { pagingSpec = function(pagingSpec); diff --git a/NzbDrone.Integration.Test/Client/ClientBase.cs b/NzbDrone.Integration.Test/Client/ClientBase.cs index 1483f9ad44..05ca16711d 100644 --- a/NzbDrone.Integration.Test/Client/ClientBase.cs +++ b/NzbDrone.Integration.Test/Client/ClientBase.cs @@ -55,6 +55,12 @@ public TResource Get(int id, HttpStatusCode statusCode = HttpStatusCode.OK) return Get(request, statusCode); } + public TResource GetSingle(HttpStatusCode statusCode = HttpStatusCode.OK) + { + var request = BuildRequest(); + return Get(request, statusCode); + } + public void Delete(int id) { var request = BuildRequest(id.ToString()); diff --git a/NzbDrone.Integration.Test/CommandIntegerationTests.cs b/NzbDrone.Integration.Test/CommandIntegerationTests.cs index 7899393d8f..c1e06bac1a 100644 --- a/NzbDrone.Integration.Test/CommandIntegerationTests.cs +++ b/NzbDrone.Integration.Test/CommandIntegerationTests.cs @@ -11,7 +11,5 @@ public void should_be_able_to_run_rss_sync() { Commands.Post(new CommandResource {Command = "rsssync"}); } - - } } \ No newline at end of file diff --git a/NzbDrone.Integration.Test/IntegrationTest.cs b/NzbDrone.Integration.Test/IntegrationTest.cs index b705146b65..3ef126a98d 100644 --- a/NzbDrone.Integration.Test/IntegrationTest.cs +++ b/NzbDrone.Integration.Test/IntegrationTest.cs @@ -3,7 +3,7 @@ using NLog.Targets; using NUnit.Framework; using NzbDrone.Api.Commands; -using NzbDrone.Api.Episodes; +using NzbDrone.Api.Config; using NzbDrone.Api.RootFolders; using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Integration.Test.Client; @@ -25,10 +25,10 @@ public abstract class IntegrationTest protected IndexerClient Indexers; protected EpisodeClient Episodes; protected SeasonClient Seasons; + protected ClientBase NamingConfig; private NzbDroneRunner _runner; - public IntegrationTest() { new StartupArguments(); @@ -42,7 +42,6 @@ public IntegrationTest() [SetUp] public void SmokeTestSetup() { - _runner = new NzbDroneRunner(); _runner.KillAll(); @@ -51,7 +50,6 @@ public void SmokeTestSetup() _runner.Start(); } - private void InitRestClients() { RestClient = new RestClient("http://localhost:8989/api"); @@ -62,6 +60,7 @@ private void InitRestClients() Indexers = new IndexerClient(RestClient); Episodes = new EpisodeClient(RestClient); Seasons = new SeasonClient(RestClient); + NamingConfig = new ClientBase(RestClient, "config/naming"); } [TearDown] diff --git a/NzbDrone.Integration.Test/NamingConfigTests.cs b/NzbDrone.Integration.Test/NamingConfigTests.cs new file mode 100644 index 0000000000..573eaf2ed8 --- /dev/null +++ b/NzbDrone.Integration.Test/NamingConfigTests.cs @@ -0,0 +1,35 @@ +using System; +using System.IO; +using FluentAssertions; +using NUnit.Framework; + +namespace NzbDrone.Integration.Test +{ + [TestFixture] + public class NamingConfigTests : IntegrationTest + { + + [Test] + public void should_be_able_to_get() + { + NamingConfig.GetSingle().Should().NotBeNull(); + } + + [Test] + public void should_be_able_to_get_by_id() + { + var config = NamingConfig.GetSingle(); + NamingConfig.Get(config.Id).Should().NotBeNull(); + NamingConfig.Get(config.Id).Id.Should().Be(config.Id); + } + + [Test] + public void should_be_able_to_update() + { + var config = NamingConfig.GetSingle(); + config.RenameEpisodes = false; + + NamingConfig.Put(config).RenameEpisodes.Should().BeFalse(); + } + } +} \ No newline at end of file diff --git a/NzbDrone.Integration.Test/NzbDrone.Integration.Test.csproj b/NzbDrone.Integration.Test/NzbDrone.Integration.Test.csproj index 04ce2753cd..2ffdbc7a97 100644 --- a/NzbDrone.Integration.Test/NzbDrone.Integration.Test.csproj +++ b/NzbDrone.Integration.Test/NzbDrone.Integration.Test.csproj @@ -99,6 +99,7 @@ + From 3a181e841c15958db3d268c0ca199d97b46e75da Mon Sep 17 00:00:00 2001 From: "kay.one" Date: Tue, 27 Aug 2013 17:40:01 -0700 Subject: [PATCH 18/58] saved changefile in ubuntu --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index d908f062f4..eb8f841a67 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,5 @@ nzbdrone {version} {branch}; urgency=low - * Automatic release. + * Automatic Release. - -- NzbDrone Mon, 27 Aug 2013 12:00:00 -0700 + -- NzbDrone Mon, 26 Aug 2013 00:00:00 -0700 From b75aad1268f3d6ebca4222bde09ffede283c7a3a Mon Sep 17 00:00:00 2001 From: Keivan Beigi Date: Wed, 28 Aug 2013 13:55:44 -0700 Subject: [PATCH 19/58] updated Owin to 2.0 RC1 --- NzbDrone.Console/NzbDrone.Console.csproj | 8 +++---- NzbDrone.Console/packages.config | 4 ++-- NzbDrone.Host/NzbDrone.Host.csproj | 12 +++++----- NzbDrone.Host/packages.config | 6 ++--- .../NzbDrone.Integration.Test.csproj | 22 ++++++++++--------- NzbDrone.Integration.Test/packages.config | 8 +++---- NzbDrone/NzbDrone.csproj | 8 +++---- NzbDrone/packages.config | 4 ++-- 8 files changed, 37 insertions(+), 35 deletions(-) diff --git a/NzbDrone.Console/NzbDrone.Console.csproj b/NzbDrone.Console/NzbDrone.Console.csproj index cec173fe15..ced3457996 100644 --- a/NzbDrone.Console/NzbDrone.Console.csproj +++ b/NzbDrone.Console/NzbDrone.Console.csproj @@ -71,13 +71,13 @@ False ..\packages\Microsoft.AspNet.SignalR.Owin.1.1.3\lib\net40\Microsoft.AspNet.SignalR.Owin.dll - + False - ..\packages\Microsoft.Owin.1.1.0-beta2\lib\net40\Microsoft.Owin.dll + ..\packages\Microsoft.Owin.2.0.0-rc1\lib\net40\Microsoft.Owin.dll - + False - ..\packages\Microsoft.Owin.Hosting.1.1.0-beta2\lib\net40\Microsoft.Owin.Hosting.dll + ..\packages\Microsoft.Owin.Hosting.2.0.0-rc1\lib\net40\Microsoft.Owin.Hosting.dll False diff --git a/NzbDrone.Console/packages.config b/NzbDrone.Console/packages.config index 19f3a3d8bb..589175f607 100644 --- a/NzbDrone.Console/packages.config +++ b/NzbDrone.Console/packages.config @@ -2,8 +2,8 @@ - - + + diff --git a/NzbDrone.Host/NzbDrone.Host.csproj b/NzbDrone.Host/NzbDrone.Host.csproj index 2eb6bcda70..ce9da2e812 100644 --- a/NzbDrone.Host/NzbDrone.Host.csproj +++ b/NzbDrone.Host/NzbDrone.Host.csproj @@ -77,17 +77,17 @@ False ..\packages\Microsoft.AspNet.SignalR.Owin.1.1.3\lib\net40\Microsoft.AspNet.SignalR.Owin.dll - + False - ..\packages\Microsoft.Owin.1.1.0-beta2\lib\net40\Microsoft.Owin.dll + ..\packages\Microsoft.Owin.2.0.0-rc1\lib\net40\Microsoft.Owin.dll - + False - ..\packages\Microsoft.Owin.Host.HttpListener.1.1.0-beta2\lib\net40\Microsoft.Owin.Host.HttpListener.dll + ..\packages\Microsoft.Owin.Host.HttpListener.2.0.0-rc1\lib\net40\Microsoft.Owin.Host.HttpListener.dll - + False - ..\packages\Microsoft.Owin.Hosting.1.1.0-beta2\lib\net40\Microsoft.Owin.Hosting.dll + ..\packages\Microsoft.Owin.Hosting.2.0.0-rc1\lib\net40\Microsoft.Owin.Hosting.dll ..\packages\Nancy.0.18.0\lib\net40\Nancy.dll diff --git a/NzbDrone.Host/packages.config b/NzbDrone.Host/packages.config index 36d7e82de0..99ec170a96 100644 --- a/NzbDrone.Host/packages.config +++ b/NzbDrone.Host/packages.config @@ -2,9 +2,9 @@ - - - + + + diff --git a/NzbDrone.Integration.Test/NzbDrone.Integration.Test.csproj b/NzbDrone.Integration.Test/NzbDrone.Integration.Test.csproj index 2ffdbc7a97..bfea57f7b3 100644 --- a/NzbDrone.Integration.Test/NzbDrone.Integration.Test.csproj +++ b/NzbDrone.Integration.Test/NzbDrone.Integration.Test.csproj @@ -40,19 +40,21 @@ False ..\packages\FluentValidation.4.0.0.1\lib\Net40\FluentValidation.dll - - ..\packages\Microsoft.AspNet.SignalR.Client.1.1.3\lib\net40\Microsoft.AspNet.SignalR.Client.dll - - - ..\packages\Microsoft.Owin.1.1.0-beta2\lib\net40\Microsoft.Owin.dll - - + False - ..\packages\Microsoft.Owin.Host.HttpListener.1.1.0-beta2\lib\net40\Microsoft.Owin.Host.HttpListener.dll + ..\packages\Microsoft.AspNet.SignalR.Client.2.0.0-rc1\lib\net40\Microsoft.AspNet.SignalR.Client.dll - + False - ..\packages\Microsoft.Owin.Hosting.1.1.0-beta2\lib\net40\Microsoft.Owin.Hosting.dll + ..\packages\Microsoft.Owin.2.0.0-rc1\lib\net40\Microsoft.Owin.dll + + + False + ..\packages\Microsoft.Owin.Host.HttpListener.2.0.0-rc1\lib\net40\Microsoft.Owin.Host.HttpListener.dll + + + False + ..\packages\Microsoft.Owin.Hosting.2.0.0-rc1\lib\net40\Microsoft.Owin.Hosting.dll False diff --git a/NzbDrone.Integration.Test/packages.config b/NzbDrone.Integration.Test/packages.config index f0ee04f810..cd41cb32b1 100644 --- a/NzbDrone.Integration.Test/packages.config +++ b/NzbDrone.Integration.Test/packages.config @@ -2,11 +2,11 @@ - - - - + + + + diff --git a/NzbDrone/NzbDrone.csproj b/NzbDrone/NzbDrone.csproj index b599ed47b0..4d447d32b1 100644 --- a/NzbDrone/NzbDrone.csproj +++ b/NzbDrone/NzbDrone.csproj @@ -71,13 +71,13 @@ False ..\packages\Microsoft.AspNet.SignalR.Owin.1.1.3\lib\net40\Microsoft.AspNet.SignalR.Owin.dll - + False - ..\packages\Microsoft.Owin.1.1.0-beta2\lib\net40\Microsoft.Owin.dll + ..\packages\Microsoft.Owin.2.0.0-rc1\lib\net40\Microsoft.Owin.dll - + False - ..\packages\Microsoft.Owin.Hosting.1.1.0-beta2\lib\net40\Microsoft.Owin.Hosting.dll + ..\packages\Microsoft.Owin.Hosting.2.0.0-rc1\lib\net40\Microsoft.Owin.Hosting.dll False diff --git a/NzbDrone/packages.config b/NzbDrone/packages.config index 907d39c5ab..3dfa2a2d58 100644 --- a/NzbDrone/packages.config +++ b/NzbDrone/packages.config @@ -2,8 +2,8 @@ - - + + \ No newline at end of file From 9b9e1e20eb035a3c026f2a79f3aa6fc8406199e2 Mon Sep 17 00:00:00 2001 From: Keivan Beigi Date: Wed, 28 Aug 2013 15:08:01 -0700 Subject: [PATCH 20/58] replaced owin's ITraceOutputFactory to one based on nlog that should work on linux. --- NzbDrone.Host/MainAppContainerBuilder.cs | 5 ++- NzbDrone.Host/NzbDrone.Host.csproj | 3 ++ NzbDrone.Host/Owin/NlogTextWriter.cs | 41 ++++++++++++++++++++ NzbDrone.Host/Owin/OwinHostController.cs | 6 ++- NzbDrone.Host/Owin/OwinServiceProvider.cs | 25 ++++++++++++ NzbDrone.Host/Owin/OwinTraceOutputFactory.cs | 14 +++++++ 6 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 NzbDrone.Host/Owin/NlogTextWriter.cs create mode 100644 NzbDrone.Host/Owin/OwinServiceProvider.cs create mode 100644 NzbDrone.Host/Owin/OwinTraceOutputFactory.cs diff --git a/NzbDrone.Host/MainAppContainerBuilder.cs b/NzbDrone.Host/MainAppContainerBuilder.cs index 51f47d4159..ecebe6e70e 100644 --- a/NzbDrone.Host/MainAppContainerBuilder.cs +++ b/NzbDrone.Host/MainAppContainerBuilder.cs @@ -1,4 +1,5 @@ -using Nancy.Bootstrapper; +using System; +using Nancy.Bootstrapper; using NzbDrone.Api; using NzbDrone.Api.SignalR; using NzbDrone.Common.Composition; @@ -6,6 +7,7 @@ using NzbDrone.Core.Datastore; using NzbDrone.Core.Organizer; using NzbDrone.Core.RootFolders; +using NzbDrone.Host.Owin; namespace NzbDrone.Host { @@ -24,6 +26,7 @@ private MainAppContainerBuilder(StartupArguments args) Container.Register(typeof(IBasicRepository), typeof(BasicRepository)); Container.Register(typeof(IBasicRepository), typeof(BasicRepository)); + Container.Register(typeof(System.IServiceProvider), typeof(OwinServiceProvider)); Container.Register(); } diff --git a/NzbDrone.Host/NzbDrone.Host.csproj b/NzbDrone.Host/NzbDrone.Host.csproj index ce9da2e812..ddb934a54b 100644 --- a/NzbDrone.Host/NzbDrone.Host.csproj +++ b/NzbDrone.Host/NzbDrone.Host.csproj @@ -122,6 +122,9 @@ + + + diff --git a/NzbDrone.Host/Owin/NlogTextWriter.cs b/NzbDrone.Host/Owin/NlogTextWriter.cs new file mode 100644 index 0000000000..d4cd4da7d8 --- /dev/null +++ b/NzbDrone.Host/Owin/NlogTextWriter.cs @@ -0,0 +1,41 @@ +using System.IO; +using System.Text; +using NLog; + +namespace NzbDrone.Host.Owin +{ + public class NlogTextWriter : TextWriter + { + private readonly Logger logger = LogManager.GetCurrentClassLogger(); + + + public override Encoding Encoding + { + get + { + return Encoding.Default; + } + } + + public override void Write(char value) + { + logger.Trace(value); + } + + public override void Write(char[] buffer) + { + logger.Trace(buffer); + } + + public override void Write(string value) + { + logger.Trace(value); + } + + public override void Write(char[] buffer, int index, int count) + { + logger.Trace(buffer); + } + + } +} \ No newline at end of file diff --git a/NzbDrone.Host/Owin/OwinHostController.cs b/NzbDrone.Host/Owin/OwinHostController.cs index 0055883b67..447ac71d06 100644 --- a/NzbDrone.Host/Owin/OwinHostController.cs +++ b/NzbDrone.Host/Owin/OwinHostController.cs @@ -14,13 +14,15 @@ public class OwinHostController : IHostController { private readonly IConfigFileProvider _configFileProvider; private readonly IEnumerable _owinMiddleWares; + private readonly IServiceProvider _serviceProvider; private readonly Logger _logger; private IDisposable _host; - public OwinHostController(IConfigFileProvider configFileProvider, IEnumerable owinMiddleWares, Logger logger) + public OwinHostController(IConfigFileProvider configFileProvider, IEnumerable owinMiddleWares, IServiceProvider serviceProvider, Logger logger) { _configFileProvider = configFileProvider; _owinMiddleWares = owinMiddleWares; + _serviceProvider = serviceProvider; _logger = logger; } @@ -37,7 +39,7 @@ public void StartServer() _logger.Info("starting server on {0}", url); - _host = WebApp.Start(options, BuildApp); + _host = WebApp.Start(_serviceProvider, options, BuildApp); } private void BuildApp(IAppBuilder appBuilder) diff --git a/NzbDrone.Host/Owin/OwinServiceProvider.cs b/NzbDrone.Host/Owin/OwinServiceProvider.cs new file mode 100644 index 0000000000..e13c76191a --- /dev/null +++ b/NzbDrone.Host/Owin/OwinServiceProvider.cs @@ -0,0 +1,25 @@ +using System; +using Microsoft.Owin.Hosting.Services; +using Microsoft.Owin.Hosting.Tracing; + +namespace NzbDrone.Host.Owin +{ + public class OwinServiceProvider : IServiceProvider + { + private readonly IServiceProvider _defaultProvider; + + public OwinServiceProvider() + { + _defaultProvider = ServicesFactory.Create(); + } + public object GetService(Type serviceType) + { + if (serviceType == typeof (ITraceOutputFactory)) + { + return new OwinTraceOutputFactory(); + } + + return _defaultProvider.GetService(serviceType); + } + } +} \ No newline at end of file diff --git a/NzbDrone.Host/Owin/OwinTraceOutputFactory.cs b/NzbDrone.Host/Owin/OwinTraceOutputFactory.cs new file mode 100644 index 0000000000..9a0f8997d6 --- /dev/null +++ b/NzbDrone.Host/Owin/OwinTraceOutputFactory.cs @@ -0,0 +1,14 @@ +using System.IO; +using Microsoft.Owin.Hosting.Tracing; + +namespace NzbDrone.Host.Owin +{ + public class OwinTraceOutputFactory : ITraceOutputFactory + { + + public TextWriter Create(string outputFile) + { + return new NlogTextWriter(); + } + } +} \ No newline at end of file From 6c7e12da5bd0736ffb291b65376b26f4e41623c3 Mon Sep 17 00:00:00 2001 From: Keivan Beigi Date: Wed, 28 Aug 2013 15:25:12 -0700 Subject: [PATCH 21/58] replaced owin's ITraceOutputFactory to one based on nlog that should work on linux. --- NzbDrone.Host/MainAppContainerBuilder.cs | 1 - NzbDrone.Host/Owin/OwinHostController.cs | 6 ++---- NzbDrone.Host/Owin/OwinServiceProvider.cs | 21 ++++++--------------- 3 files changed, 8 insertions(+), 20 deletions(-) diff --git a/NzbDrone.Host/MainAppContainerBuilder.cs b/NzbDrone.Host/MainAppContainerBuilder.cs index ecebe6e70e..e12fc91531 100644 --- a/NzbDrone.Host/MainAppContainerBuilder.cs +++ b/NzbDrone.Host/MainAppContainerBuilder.cs @@ -26,7 +26,6 @@ private MainAppContainerBuilder(StartupArguments args) Container.Register(typeof(IBasicRepository), typeof(BasicRepository)); Container.Register(typeof(IBasicRepository), typeof(BasicRepository)); - Container.Register(typeof(System.IServiceProvider), typeof(OwinServiceProvider)); Container.Register(); } diff --git a/NzbDrone.Host/Owin/OwinHostController.cs b/NzbDrone.Host/Owin/OwinHostController.cs index 447ac71d06..a571d55304 100644 --- a/NzbDrone.Host/Owin/OwinHostController.cs +++ b/NzbDrone.Host/Owin/OwinHostController.cs @@ -14,15 +14,13 @@ public class OwinHostController : IHostController { private readonly IConfigFileProvider _configFileProvider; private readonly IEnumerable _owinMiddleWares; - private readonly IServiceProvider _serviceProvider; private readonly Logger _logger; private IDisposable _host; - public OwinHostController(IConfigFileProvider configFileProvider, IEnumerable owinMiddleWares, IServiceProvider serviceProvider, Logger logger) + public OwinHostController(IConfigFileProvider configFileProvider, IEnumerable owinMiddleWares, Logger logger) { _configFileProvider = configFileProvider; _owinMiddleWares = owinMiddleWares; - _serviceProvider = serviceProvider; _logger = logger; } @@ -39,7 +37,7 @@ public void StartServer() _logger.Info("starting server on {0}", url); - _host = WebApp.Start(_serviceProvider, options, BuildApp); + _host = WebApp.Start(OwinServiceProviderFactory.Create(), options, BuildApp); } private void BuildApp(IAppBuilder appBuilder) diff --git a/NzbDrone.Host/Owin/OwinServiceProvider.cs b/NzbDrone.Host/Owin/OwinServiceProvider.cs index e13c76191a..cffea738f2 100644 --- a/NzbDrone.Host/Owin/OwinServiceProvider.cs +++ b/NzbDrone.Host/Owin/OwinServiceProvider.cs @@ -1,25 +1,16 @@ -using System; -using Microsoft.Owin.Hosting.Services; +using Microsoft.Owin.Hosting.Services; using Microsoft.Owin.Hosting.Tracing; namespace NzbDrone.Host.Owin { - public class OwinServiceProvider : IServiceProvider + public static class OwinServiceProviderFactory { - private readonly IServiceProvider _defaultProvider; - - public OwinServiceProvider() + public static ServiceProvider Create() { - _defaultProvider = ServicesFactory.Create(); - } - public object GetService(Type serviceType) - { - if (serviceType == typeof (ITraceOutputFactory)) - { - return new OwinTraceOutputFactory(); - } + var provider = (ServiceProvider)ServicesFactory.Create(); + provider.Add(typeof(ITraceOutputFactory), typeof(OwinTraceOutputFactory)); - return _defaultProvider.GetService(serviceType); + return provider; } } } \ No newline at end of file From 64ab411ba30a623ea58183d7a1619cd891a4a644 Mon Sep 17 00:00:00 2001 From: Keivan Beigi Date: Wed, 28 Aug 2013 16:14:31 -0700 Subject: [PATCH 22/58] added logging to integration test runner for status call. --- NzbDrone.Integration.Test/NzbDroneRunner.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/NzbDrone.Integration.Test/NzbDroneRunner.cs b/NzbDrone.Integration.Test/NzbDroneRunner.cs index 988c472780..cde91b605d 100644 --- a/NzbDrone.Integration.Test/NzbDroneRunner.cs +++ b/NzbDrone.Integration.Test/NzbDroneRunner.cs @@ -53,11 +53,16 @@ public void Start() Assert.Fail("Process has exited"); } - if (_restClient.Get(new RestRequest("system/status")).ResponseStatus == ResponseStatus.Completed) + + var statusCall = _restClient.Get(new RestRequest("system/status")); + + if (statusCall.ResponseStatus == ResponseStatus.Completed) { return; } + Console.WriteLine("Waiting for NzbDrone to start. Response Status : {0} [{1}] {2}", statusCall.ResponseStatus, statusCall.StatusDescription, statusCall.ErrorException); + Thread.Sleep(500); } } From 1f90d546d4405910eaae34d3868cfee367d30715 Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Wed, 28 Aug 2013 08:15:49 -0700 Subject: [PATCH 23/58] Fixed some help icons that were pointing at old names --- UI/Settings/DownloadClient/BlackholeViewTemplate.html | 2 +- UI/Settings/DownloadClient/LayoutTemplate.html | 2 +- UI/Settings/DownloadClient/NzbgetViewTemplate.html | 4 ++-- UI/Settings/DownloadClient/PneumaticViewTemplate.html | 2 +- UI/Settings/DownloadClient/SabViewTemplate.html | 6 +++--- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/UI/Settings/DownloadClient/BlackholeViewTemplate.html b/UI/Settings/DownloadClient/BlackholeViewTemplate.html index 05d9e78ced..e41520b2fc 100644 --- a/UI/Settings/DownloadClient/BlackholeViewTemplate.html +++ b/UI/Settings/DownloadClient/BlackholeViewTemplate.html @@ -6,7 +6,7 @@
- +
diff --git a/UI/Settings/DownloadClient/LayoutTemplate.html b/UI/Settings/DownloadClient/LayoutTemplate.html index 9d66916f53..54c0c81f64 100644 --- a/UI/Settings/DownloadClient/LayoutTemplate.html +++ b/UI/Settings/DownloadClient/LayoutTemplate.html @@ -19,7 +19,7 @@
- +
diff --git a/UI/Settings/DownloadClient/NzbgetViewTemplate.html b/UI/Settings/DownloadClient/NzbgetViewTemplate.html index cc29f4a3a7..cae6ec715f 100644 --- a/UI/Settings/DownloadClient/NzbgetViewTemplate.html +++ b/UI/Settings/DownloadClient/NzbgetViewTemplate.html @@ -61,7 +61,7 @@ - + @@ -79,7 +79,7 @@ - + diff --git a/UI/Settings/DownloadClient/PneumaticViewTemplate.html b/UI/Settings/DownloadClient/PneumaticViewTemplate.html index 791b212ba1..8fc612fc3d 100644 --- a/UI/Settings/DownloadClient/PneumaticViewTemplate.html +++ b/UI/Settings/DownloadClient/PneumaticViewTemplate.html @@ -6,7 +6,7 @@
- +
diff --git a/UI/Settings/DownloadClient/SabViewTemplate.html b/UI/Settings/DownloadClient/SabViewTemplate.html index 8bdd39afd0..25ae6e74a1 100644 --- a/UI/Settings/DownloadClient/SabViewTemplate.html +++ b/UI/Settings/DownloadClient/SabViewTemplate.html @@ -70,11 +70,11 @@ - + - + @@ -92,7 +92,7 @@ - + From 9e5353aaccf65f45b5f97729b309da39ed592dbe Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Wed, 28 Aug 2013 18:43:45 -0700 Subject: [PATCH 24/58] Cleanup orphaned seasons when deleting episodes --- NzbDrone.Core.Test/NzbDrone.Core.Test.csproj | 1 + .../HandleEpisodeInfoDeletedEventFixture.cs | 93 ++++++++++++++++++ NzbDrone.Core/NzbDrone.Core.csproj | 1 + .../Tv/Events/EpisodeInfoDeletedEvent.cs | 16 +++ NzbDrone.Core/Tv/RefreshEpisodeService.cs | 14 ++- NzbDrone.Core/Tv/SeasonService.cs | Bin 8572 -> 9871 bytes 6 files changed, 120 insertions(+), 5 deletions(-) create mode 100644 NzbDrone.Core.Test/TvTests/SeasonServiceTests/HandleEpisodeInfoDeletedEventFixture.cs create mode 100644 NzbDrone.Core/Tv/Events/EpisodeInfoDeletedEvent.cs diff --git a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj index b3e34350c8..0d3bd36342 100644 --- a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -186,6 +186,7 @@ + diff --git a/NzbDrone.Core.Test/TvTests/SeasonServiceTests/HandleEpisodeInfoDeletedEventFixture.cs b/NzbDrone.Core.Test/TvTests/SeasonServiceTests/HandleEpisodeInfoDeletedEventFixture.cs new file mode 100644 index 0000000000..d31c2b6794 --- /dev/null +++ b/NzbDrone.Core.Test/TvTests/SeasonServiceTests/HandleEpisodeInfoDeletedEventFixture.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using FizzWare.NBuilder; +using Moq; +using NUnit.Framework; +using NzbDrone.Core.Test.Framework; +using NzbDrone.Core.Tv; +using NzbDrone.Core.Tv.Events; + +namespace NzbDrone.Core.Test.TvTests.SeasonServiceTests +{ + [TestFixture] + public class HandleEpisodeInfoDeletedEventFixture : CoreTest + { + private List _seasons; + private List _episodes; + + [SetUp] + public void Setup() + { + _seasons = Builder + .CreateListOfSize(1) + .All() + .With(s => s.SeriesId = 1) + .Build() + .ToList(); + + _episodes = Builder + .CreateListOfSize(1) + .All() + .With(e => e.SeasonNumber = _seasons.First().SeasonNumber) + .With(s => s.SeriesId = _seasons.First().SeasonNumber) + .Build() + .ToList(); + + Mocker.GetMock() + .Setup(s => s.GetSeasonBySeries(It.IsAny())) + .Returns(_seasons); + + Mocker.GetMock() + .Setup(s => s.GetEpisodesBySeason(It.IsAny(), _seasons.First().SeasonNumber)) + .Returns(_episodes); + } + + private void GivenAbandonedSeason() + { + Mocker.GetMock() + .Setup(s => s.GetEpisodesBySeason(It.IsAny(), _seasons.First().SeasonNumber)) + .Returns(new List()); + } + + [Test] + public void should_not_delete_when_season_is_still_valid() + { + Subject.Handle(new EpisodeInfoDeletedEvent(_episodes)); + + Mocker.GetMock() + .Verify(v => v.Delete(It.IsAny()), Times.Never()); + } + + [Test] + public void should_delete_season_if_no_episodes_exist_in_that_season() + { + GivenAbandonedSeason(); + + Subject.Handle(new EpisodeInfoDeletedEvent(_episodes)); + + Mocker.GetMock() + .Verify(v => v.Delete(It.IsAny()), Times.Once()); + } + + [Test] + public void should_only_delete_a_season_once() + { + _episodes = Builder + .CreateListOfSize(5) + .All() + .With(e => e.SeasonNumber = _seasons.First().SeasonNumber) + .With(s => s.SeriesId = _seasons.First().SeasonNumber) + .Build() + .ToList(); + + GivenAbandonedSeason(); + + Subject.Handle(new EpisodeInfoDeletedEvent(_episodes)); + + Mocker.GetMock() + .Verify(v => v.Delete(It.IsAny()), Times.Once()); + } + } +} diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index a774cc3fd7..9ed55a6ff0 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -350,6 +350,7 @@ + diff --git a/NzbDrone.Core/Tv/Events/EpisodeInfoDeletedEvent.cs b/NzbDrone.Core/Tv/Events/EpisodeInfoDeletedEvent.cs new file mode 100644 index 0000000000..864445e58e --- /dev/null +++ b/NzbDrone.Core/Tv/Events/EpisodeInfoDeletedEvent.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; +using NzbDrone.Common.Messaging; + +namespace NzbDrone.Core.Tv.Events +{ + public class EpisodeInfoDeletedEvent : IEvent + { + public ReadOnlyCollection Episodes { get; private set; } + + public EpisodeInfoDeletedEvent(IList episodes) + { + Episodes = new ReadOnlyCollection(episodes); + } + } +} \ No newline at end of file diff --git a/NzbDrone.Core/Tv/RefreshEpisodeService.cs b/NzbDrone.Core/Tv/RefreshEpisodeService.cs index 14140ba842..c62d8a5d23 100644 --- a/NzbDrone.Core/Tv/RefreshEpisodeService.cs +++ b/NzbDrone.Core/Tv/RefreshEpisodeService.cs @@ -34,7 +34,7 @@ public void RefreshEpisodeInfo(Series series, IEnumerable remoteEpisode var successCount = 0; var failCount = 0; - var existinEpisodes = _episodeService.GetEpisodeBySeries(series.Id); + var existingEpisodes = _episodeService.GetEpisodeBySeries(series.Id); var seasons = _seasonService.GetSeasonsBySeries(series.Id); var updateList = new List(); @@ -44,11 +44,11 @@ public void RefreshEpisodeInfo(Series series, IEnumerable remoteEpisode { try { - var episodeToUpdate = existinEpisodes.SingleOrDefault(e => e.SeasonNumber == episode.SeasonNumber && e.EpisodeNumber == episode.EpisodeNumber); + var episodeToUpdate = existingEpisodes.SingleOrDefault(e => e.SeasonNumber == episode.SeasonNumber && e.EpisodeNumber == episode.EpisodeNumber); if (episodeToUpdate != null) { - existinEpisodes.Remove(episodeToUpdate); + existingEpisodes.Remove(episodeToUpdate); updateList.Add(episodeToUpdate); } else @@ -82,11 +82,10 @@ public void RefreshEpisodeInfo(Series series, IEnumerable remoteEpisode AdjustMultiEpisodeAirTime(series, allEpisodes); - _episodeService.DeleteMany(existinEpisodes); + _episodeService.DeleteMany(existingEpisodes); _episodeService.UpdateMany(updateList); _episodeService.InsertMany(newList); - if (newList.Any()) { _messageAggregator.PublishEvent(new EpisodeInfoAddedEvent(newList, series)); @@ -97,6 +96,11 @@ public void RefreshEpisodeInfo(Series series, IEnumerable remoteEpisode _messageAggregator.PublishEvent(new EpisodeInfoUpdatedEvent(updateList)); } + if (existingEpisodes.Any()) + { + _messageAggregator.PublishEvent(new EpisodeInfoDeletedEvent(updateList)); + } + if (failCount != 0) { _logger.Info("Finished episode refresh for series: {0}. Successful: {1} - Failed: {2} ", diff --git a/NzbDrone.Core/Tv/SeasonService.cs b/NzbDrone.Core/Tv/SeasonService.cs index 8cb3d0c75795638537f01c86fdb483b545701f5e..6355796a47cb4e1da5460d78e1594785dad261cc 100644 GIT binary patch delta 586 zcmZ`$O-tNR6ooWuVm@A;bY^Om_O+YNSQ${)V^JJR7uLa9xGbr;Qy;_^O)>!mS8hZE zh4UlamBLWyZ|Gm>raPB*;ie$1$;?#5wr};g=iGD7z4vfcls1P6miGo3stLuC zk~hKZUt0Z)wfd6UtJZ4p%<}E>*JDA1py4o*Cyf93s& z$+4jfT=Nl3i($kn!?p~3=TGt5v2pBN;L;k!l~d7+i-Wl{?!B|Ua_0+9?}{I>8zzy! Ao&W#< delta 98 zcmeD8{o}MDjcGC~v+(3eOk!aA3X{ZUPv*^Blk0fcCfA6GPwp3ezWEPt9@FFkCYH&$ h!s1}MQ9uh!uNF`T)0YI4!1Nb^La0XW%|ha}`~Y6UASM6+ From 5dc3a3223dce293595805259d9fc8d4d5aa38c7b Mon Sep 17 00:00:00 2001 From: "kay.one" Date: Thu, 29 Aug 2013 11:34:53 -0700 Subject: [PATCH 25/58] Revert "updated Owin to 2.0 RC1" This reverts commit b75aad1268f3d6ebca4222bde09ffede283c7a3a. --- NzbDrone.Console/NzbDrone.Console.csproj | 8 ++++---- NzbDrone.Console/packages.config | 4 ++-- NzbDrone.Host/NzbDrone.Host.csproj | 12 ++++++------ NzbDrone.Host/packages.config | 6 +++--- .../NzbDrone.Integration.Test.csproj | 18 ++++++++---------- NzbDrone.Integration.Test/packages.config | 8 ++++---- NzbDrone/NzbDrone.csproj | 8 ++++---- NzbDrone/packages.config | 4 ++-- 8 files changed, 33 insertions(+), 35 deletions(-) diff --git a/NzbDrone.Console/NzbDrone.Console.csproj b/NzbDrone.Console/NzbDrone.Console.csproj index ced3457996..cec173fe15 100644 --- a/NzbDrone.Console/NzbDrone.Console.csproj +++ b/NzbDrone.Console/NzbDrone.Console.csproj @@ -71,13 +71,13 @@ False ..\packages\Microsoft.AspNet.SignalR.Owin.1.1.3\lib\net40\Microsoft.AspNet.SignalR.Owin.dll
- + False - ..\packages\Microsoft.Owin.2.0.0-rc1\lib\net40\Microsoft.Owin.dll + ..\packages\Microsoft.Owin.1.1.0-beta2\lib\net40\Microsoft.Owin.dll - + False - ..\packages\Microsoft.Owin.Hosting.2.0.0-rc1\lib\net40\Microsoft.Owin.Hosting.dll + ..\packages\Microsoft.Owin.Hosting.1.1.0-beta2\lib\net40\Microsoft.Owin.Hosting.dll False diff --git a/NzbDrone.Console/packages.config b/NzbDrone.Console/packages.config index 589175f607..19f3a3d8bb 100644 --- a/NzbDrone.Console/packages.config +++ b/NzbDrone.Console/packages.config @@ -2,8 +2,8 @@ - - + + diff --git a/NzbDrone.Host/NzbDrone.Host.csproj b/NzbDrone.Host/NzbDrone.Host.csproj index ddb934a54b..c625626eae 100644 --- a/NzbDrone.Host/NzbDrone.Host.csproj +++ b/NzbDrone.Host/NzbDrone.Host.csproj @@ -77,17 +77,17 @@ False ..\packages\Microsoft.AspNet.SignalR.Owin.1.1.3\lib\net40\Microsoft.AspNet.SignalR.Owin.dll - + False - ..\packages\Microsoft.Owin.2.0.0-rc1\lib\net40\Microsoft.Owin.dll + ..\packages\Microsoft.Owin.1.1.0-beta2\lib\net40\Microsoft.Owin.dll - + False - ..\packages\Microsoft.Owin.Host.HttpListener.2.0.0-rc1\lib\net40\Microsoft.Owin.Host.HttpListener.dll + ..\packages\Microsoft.Owin.Host.HttpListener.1.1.0-beta2\lib\net40\Microsoft.Owin.Host.HttpListener.dll - + False - ..\packages\Microsoft.Owin.Hosting.2.0.0-rc1\lib\net40\Microsoft.Owin.Hosting.dll + ..\packages\Microsoft.Owin.Hosting.1.1.0-beta2\lib\net40\Microsoft.Owin.Hosting.dll ..\packages\Nancy.0.18.0\lib\net40\Nancy.dll diff --git a/NzbDrone.Host/packages.config b/NzbDrone.Host/packages.config index 99ec170a96..36d7e82de0 100644 --- a/NzbDrone.Host/packages.config +++ b/NzbDrone.Host/packages.config @@ -2,9 +2,9 @@ - - - + + + diff --git a/NzbDrone.Integration.Test/NzbDrone.Integration.Test.csproj b/NzbDrone.Integration.Test/NzbDrone.Integration.Test.csproj index bfea57f7b3..2ffdbc7a97 100644 --- a/NzbDrone.Integration.Test/NzbDrone.Integration.Test.csproj +++ b/NzbDrone.Integration.Test/NzbDrone.Integration.Test.csproj @@ -40,21 +40,19 @@ False ..\packages\FluentValidation.4.0.0.1\lib\Net40\FluentValidation.dll - - False - ..\packages\Microsoft.AspNet.SignalR.Client.2.0.0-rc1\lib\net40\Microsoft.AspNet.SignalR.Client.dll + + ..\packages\Microsoft.AspNet.SignalR.Client.1.1.3\lib\net40\Microsoft.AspNet.SignalR.Client.dll - - False - ..\packages\Microsoft.Owin.2.0.0-rc1\lib\net40\Microsoft.Owin.dll + + ..\packages\Microsoft.Owin.1.1.0-beta2\lib\net40\Microsoft.Owin.dll - + False - ..\packages\Microsoft.Owin.Host.HttpListener.2.0.0-rc1\lib\net40\Microsoft.Owin.Host.HttpListener.dll + ..\packages\Microsoft.Owin.Host.HttpListener.1.1.0-beta2\lib\net40\Microsoft.Owin.Host.HttpListener.dll - + False - ..\packages\Microsoft.Owin.Hosting.2.0.0-rc1\lib\net40\Microsoft.Owin.Hosting.dll + ..\packages\Microsoft.Owin.Hosting.1.1.0-beta2\lib\net40\Microsoft.Owin.Hosting.dll False diff --git a/NzbDrone.Integration.Test/packages.config b/NzbDrone.Integration.Test/packages.config index cd41cb32b1..f0ee04f810 100644 --- a/NzbDrone.Integration.Test/packages.config +++ b/NzbDrone.Integration.Test/packages.config @@ -2,11 +2,11 @@ + + + + - - - - diff --git a/NzbDrone/NzbDrone.csproj b/NzbDrone/NzbDrone.csproj index 4d447d32b1..b599ed47b0 100644 --- a/NzbDrone/NzbDrone.csproj +++ b/NzbDrone/NzbDrone.csproj @@ -71,13 +71,13 @@ False ..\packages\Microsoft.AspNet.SignalR.Owin.1.1.3\lib\net40\Microsoft.AspNet.SignalR.Owin.dll - + False - ..\packages\Microsoft.Owin.2.0.0-rc1\lib\net40\Microsoft.Owin.dll + ..\packages\Microsoft.Owin.1.1.0-beta2\lib\net40\Microsoft.Owin.dll - + False - ..\packages\Microsoft.Owin.Hosting.2.0.0-rc1\lib\net40\Microsoft.Owin.Hosting.dll + ..\packages\Microsoft.Owin.Hosting.1.1.0-beta2\lib\net40\Microsoft.Owin.Hosting.dll False diff --git a/NzbDrone/packages.config b/NzbDrone/packages.config index 3dfa2a2d58..907d39c5ab 100644 --- a/NzbDrone/packages.config +++ b/NzbDrone/packages.config @@ -2,8 +2,8 @@ - - + + \ No newline at end of file From ef32431682e1ae965010345c9a2d4c1a314dd363 Mon Sep 17 00:00:00 2001 From: "kay.one" Date: Thu, 29 Aug 2013 18:26:03 -0700 Subject: [PATCH 26/58] GetActualCasing can partially fix the path for non-existing paths. --- NzbDrone.Common.Test/PathExtensionFixture.cs | 21 ++++++++++---------- NzbDrone.Common/PathExtensions.cs | 14 ++++++++----- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/NzbDrone.Common.Test/PathExtensionFixture.cs b/NzbDrone.Common.Test/PathExtensionFixture.cs index 7393447278..907d13d4c2 100644 --- a/NzbDrone.Common.Test/PathExtensionFixture.cs +++ b/NzbDrone.Common.Test/PathExtensionFixture.cs @@ -102,10 +102,18 @@ public void normalize_path_exception_null() } [Test] - public void get_actual_casing_for_none_existing_file_should_throw() + public void get_actual_casing_for_none_existing_file_return_partially_fixed_result() { WindowsOnly(); - Assert.Throws(() => "C:\\InValidFolder\\invalidfile.exe".GetActualCasing()); + "C:\\WINDOWS\\invalidfile.exe".GetActualCasing().Should().Be("C:\\Windows\\invalidfile.exe"); + } + + + [Test] + public void get_actual_casing_for_none_existing_folder_return_partially_fixed_result() + { + WindowsOnly(); + "C:\\WINDOWS\\SYSTEM32\\FAKEFOLDER\\invalidfile.exe".GetActualCasing().Should().Be("C:\\Windows\\System32\\FAKEFOLDER\\invalidfile.exe"); } [Test] @@ -117,14 +125,7 @@ public void get_actual_casing_should_return_actual_casing_for_local_file_in_wind path.ToLower().GetActualCasing().Should().Be(path); } - [Test] - public void get_actual_casing_should_return_origibal_value_in_linux() - { - LinuxOnly(); - var path = Process.GetCurrentProcess().MainModule.FileName; - path.GetActualCasing().Should().Be(path); - path.GetActualCasing().Should().Be(path); - } + [Test] public void get_actual_casing_should_return_actual_casing_for_local_dir_in_windows() diff --git a/NzbDrone.Common/PathExtensions.cs b/NzbDrone.Common/PathExtensions.cs index 15e3b8a08f..b5e899eba0 100644 --- a/NzbDrone.Common/PathExtensions.cs +++ b/NzbDrone.Common/PathExtensions.cs @@ -63,23 +63,27 @@ private static string GetProperCapitalization(DirectoryInfo dirInfo) public static string GetActualCasing(this string path) { - var attributes = File.GetAttributes(path); - if (OsInfo.IsLinux || path.StartsWith("\\")) { return path; } - if ((attributes & FileAttributes.Directory) == FileAttributes.Directory) + if (Directory.Exists(path) && (File.GetAttributes(path) & FileAttributes.Directory) == FileAttributes.Directory) { return GetProperCapitalization(new DirectoryInfo(path)); } var fileInfo = new FileInfo(path); + var dirInfo = fileInfo.Directory; + var fileName = fileInfo.Name; - DirectoryInfo dirInfo = fileInfo.Directory; - return Path.Combine(GetProperCapitalization(dirInfo), dirInfo.GetFiles(fileInfo.Name)[0].Name); + if (dirInfo != null && fileInfo.Exists) + { + fileName = dirInfo.GetFiles(fileInfo.Name)[0].Name; + } + + return Path.Combine(GetProperCapitalization(dirInfo), fileName); } public static string GetAppDataPath(this IAppFolderInfo appFolderInfo) From a22cbfee2fc5526f95f557ddbdbe59e7919fcd34 Mon Sep 17 00:00:00 2001 From: "kay.one" Date: Thu, 29 Aug 2013 18:32:25 -0700 Subject: [PATCH 27/58] handle empty rss response from indexers. --- NzbDrone.Core/Indexers/BasicRssParser.cs | 50 ++++++++++--------- NzbDrone.Core/Indexers/IndexerFetchService.cs | 12 ++++- 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/NzbDrone.Core/Indexers/BasicRssParser.cs b/NzbDrone.Core/Indexers/BasicRssParser.cs index d298892485..17963956c5 100644 --- a/NzbDrone.Core/Indexers/BasicRssParser.cs +++ b/NzbDrone.Core/Indexers/BasicRssParser.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Text.RegularExpressions; +using System.Xml; using System.Xml.Linq; using NLog; using NzbDrone.Core.Parser.Model; @@ -12,7 +13,7 @@ namespace NzbDrone.Core.Indexers { public interface IParseFeed { - IEnumerable Process(Stream source, string url); + IEnumerable Process(string xml, string url); } public class BasicRssParser : IParseFeed @@ -24,34 +25,37 @@ public BasicRssParser() _logger = LogManager.GetCurrentClassLogger(); } - public IEnumerable Process(Stream source, string url) + public IEnumerable Process(string xml, string url) { - var document = XDocument.Load(source); - var items = document.Descendants("item"); - - var result = new List(); - - foreach (var item in items) + using (var xmlTextReader = new XmlTextReader(new StringReader(xml)) { DtdProcessing = DtdProcessing.Ignore }) { - try - { - var reportInfo = ParseFeedItem(item); - if (reportInfo != null) - { - reportInfo.NzbUrl = GetNzbUrl(item); - reportInfo.NzbInfoUrl = GetNzbInfoUrl(item); + var document = XDocument.Load(xmlTextReader); + var items = document.Descendants("item"); - result.Add(reportInfo); + var result = new List(); + + foreach (var item in items) + { + try + { + var reportInfo = ParseFeedItem(item); + if (reportInfo != null) + { + reportInfo.NzbUrl = GetNzbUrl(item); + reportInfo.NzbInfoUrl = GetNzbInfoUrl(item); + + result.Add(reportInfo); + } + } + catch (Exception itemEx) + { + itemEx.Data.Add("Item", item.Title()); + _logger.ErrorException("An error occurred while processing feed item from " + url, itemEx); } } - catch (Exception itemEx) - { - itemEx.Data.Add("Item", item.Title()); - _logger.ErrorException("An error occurred while processing feed item from " + url, itemEx); - } - } - return result; + return result; + } } diff --git a/NzbDrone.Core/Indexers/IndexerFetchService.cs b/NzbDrone.Core/Indexers/IndexerFetchService.cs index 6c46032b64..63a2c5e6ba 100644 --- a/NzbDrone.Core/Indexers/IndexerFetchService.cs +++ b/NzbDrone.Core/Indexers/IndexerFetchService.cs @@ -106,8 +106,16 @@ private List Fetch(IIndexer indexer, IEnumerable urls) try { _logger.Trace("Downloading Feed " + url); - var stream = _httpProvider.DownloadStream(url); - result.AddRange(indexer.Parser.Process(stream, url)); + var xml = _httpProvider.DownloadString(url); + if (!string.IsNullOrWhiteSpace(xml)) + { + result.AddRange(indexer.Parser.Process(xml, url)); + } + else + { + _logger.Warn("{0} returned empty response.", url); + } + } catch (WebException webException) { From 47e29abc2767a200d373e049a4aa6d305624c701 Mon Sep 17 00:00:00 2001 From: "kay.one" Date: Thu, 29 Aug 2013 18:38:43 -0700 Subject: [PATCH 28/58] don't log indexer errors as exceptions. --- NzbDrone.Core/Indexers/IndexerFetchService.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/NzbDrone.Core/Indexers/IndexerFetchService.cs b/NzbDrone.Core/Indexers/IndexerFetchService.cs index 63a2c5e6ba..2e585f8621 100644 --- a/NzbDrone.Core/Indexers/IndexerFetchService.cs +++ b/NzbDrone.Core/Indexers/IndexerFetchService.cs @@ -119,14 +119,13 @@ private List Fetch(IIndexer indexer, IEnumerable urls) } catch (WebException webException) { - if (webException.Message.Contains("503") || webException.Message.Contains("timed out")) + if (webException.Message.Contains("502") || webException.Message.Contains("503") || webException.Message.Contains("timed out")) { _logger.Warn("{0} server is currently unavailable. {1} {2}", indexer.Name, url, webException.Message); } else { - webException.Data.Add("FeedUrl", url); - _logger.WarnException("An error occurred while processing feed. " + url, webException); + _logger.Warn("{0} {1} {2}", indexer.Name, url, webException.Message); } } catch (Exception feedEx) From 76c7d75c31cc914d097d44289c135c504e2bffca Mon Sep 17 00:00:00 2001 From: "kay.one" Date: Thu, 29 Aug 2013 18:55:42 -0700 Subject: [PATCH 29/58] added some test for free space. --- .../DiskProviderTests/FreeSpaceFixture.cs | 40 +++++++++++++++++++ .../DiskProviderTests/IsParentFixture.cs | 28 ++++++------- .../NzbDrone.Common.Test.csproj | 1 + 3 files changed, 55 insertions(+), 14 deletions(-) create mode 100644 NzbDrone.Common.Test/DiskProviderTests/FreeSpaceFixture.cs diff --git a/NzbDrone.Common.Test/DiskProviderTests/FreeSpaceFixture.cs b/NzbDrone.Common.Test/DiskProviderTests/FreeSpaceFixture.cs new file mode 100644 index 0000000000..8359ad4819 --- /dev/null +++ b/NzbDrone.Common.Test/DiskProviderTests/FreeSpaceFixture.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Test.Common; + +namespace NzbDrone.Common.Test.DiskProviderTests +{ + [TestFixture] + public class IsParentFixture : TestBase + { + private string _parent = @"C:\Test".AsOsAgnostic(); + + [Test] + public void should_return_false_when_not_a_child() + { + var path = @"C:\Another Folder".AsOsAgnostic(); + + Subject.IsParent(_parent, path).Should().BeFalse(); + } + + [Test] + public void should_return_true_when_folder_is_parent_of_another_folder() + { + var path = @"C:\Test\TV".AsOsAgnostic(); + + Subject.IsParent(_parent, path).Should().BeTrue(); + } + + [Test] + public void should_return_true_when_folder_is_parent_of_a_file() + { + var path = @"C:\Test\30.Rock.S01E01.Pilot.avi".AsOsAgnostic(); + + Subject.IsParent(_parent, path).Should().BeTrue(); + } + } +} diff --git a/NzbDrone.Common.Test/DiskProviderTests/IsParentFixture.cs b/NzbDrone.Common.Test/DiskProviderTests/IsParentFixture.cs index 8359ad4819..a17595a6e0 100644 --- a/NzbDrone.Common.Test/DiskProviderTests/IsParentFixture.cs +++ b/NzbDrone.Common.Test/DiskProviderTests/IsParentFixture.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; using FluentAssertions; @@ -9,32 +10,31 @@ namespace NzbDrone.Common.Test.DiskProviderTests { [TestFixture] - public class IsParentFixture : TestBase + public class FreeSpaceFixture : TestBase { - private string _parent = @"C:\Test".AsOsAgnostic(); - [Test] - public void should_return_false_when_not_a_child() + public void should_get_free_space_for_folder() { - var path = @"C:\Another Folder".AsOsAgnostic(); + var path = @"C:\".AsOsAgnostic(); - Subject.IsParent(_parent, path).Should().BeFalse(); + Subject.GetAvilableSpace(path).Should().NotBe(0); } [Test] - public void should_return_true_when_folder_is_parent_of_another_folder() + public void should_get_free_space_for_folder_that_doesnt_exist() { - var path = @"C:\Test\TV".AsOsAgnostic(); + var path = @"C:\".AsOsAgnostic(); - Subject.IsParent(_parent, path).Should().BeTrue(); + Subject.GetAvilableSpace(Path.Combine(path, "invalidFolder")).Should().NotBe(0); } - [Test] - public void should_return_true_when_folder_is_parent_of_a_file() - { - var path = @"C:\Test\30.Rock.S01E01.Pilot.avi".AsOsAgnostic(); - Subject.IsParent(_parent, path).Should().BeTrue(); + [Test] + public void should_get_free_space_for_drive_that_doesnt_exist() + { + WindowsOnly(); + + Subject.GetAvilableSpace("J:\\").Should().NotBe(0); } } } diff --git a/NzbDrone.Common.Test/NzbDrone.Common.Test.csproj b/NzbDrone.Common.Test/NzbDrone.Common.Test.csproj index 1dd3ccd786..15bb183eed 100644 --- a/NzbDrone.Common.Test/NzbDrone.Common.Test.csproj +++ b/NzbDrone.Common.Test/NzbDrone.Common.Test.csproj @@ -62,6 +62,7 @@ + From 84857f286a20124f76edfb5966d58484ccfbc911 Mon Sep 17 00:00:00 2001 From: "kay.one" Date: Thu, 29 Aug 2013 19:00:40 -0700 Subject: [PATCH 30/58] handle exceptions when getting header for covers fail. --- NzbDrone.Core/MediaCover/MediaCoverService.cs | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/NzbDrone.Core/MediaCover/MediaCoverService.cs b/NzbDrone.Core/MediaCover/MediaCoverService.cs index 99f10e4e70..b14a6bcb30 100644 --- a/NzbDrone.Core/MediaCover/MediaCoverService.cs +++ b/NzbDrone.Core/MediaCover/MediaCoverService.cs @@ -44,30 +44,31 @@ private void EnsureCovers(Series series) foreach (var cover in series.Images) { var fileName = GetCoverPath(series.Id, cover.CoverType); - if (!_coverExistsSpecification.AlreadyExists(cover.Url, fileName)) + try { - DownloadCover(series, cover); + if (!_coverExistsSpecification.AlreadyExists(cover.Url, fileName)) + { + DownloadCover(series, cover); + } + } + catch (WebException e) + { + _logger.Warn(string.Format("Couldn't download media cover for {0}. {1}", series, e.Message); + } + catch (Exception e) + { + _logger.ErrorException("Couldn't download media cover for " + series, e); } } } private void DownloadCover(Series series, MediaCover cover) { - try - { - var fileName = GetCoverPath(series.Id, cover.CoverType); + var fileName = GetCoverPath(series.Id, cover.CoverType); + + _logger.Info("Downloading {0} for {1} {2}", cover.CoverType, series, cover.Url); + _httpProvider.DownloadFile(cover.Url, fileName); - _logger.Info("Downloading {0} for {1} {2}", cover.CoverType, series, cover.Url); - _httpProvider.DownloadFile(cover.Url, fileName); - } - catch (WebException e) - { - _logger.Warn("Couldn't download media cover for " + series); - } - catch (Exception e) - { - _logger.ErrorException("Couldn't download media cover for " + series, e); - } } public void HandleAsync(SeriesDeletedEvent message) From 25e6473537f9cc45c42b678d9f9dc7dba2961647 Mon Sep 17 00:00:00 2001 From: "kay.one" Date: Thu, 29 Aug 2013 19:05:33 -0700 Subject: [PATCH 31/58] fixed broken build. --- NzbDrone.Common.Test/DiskProviderTests/IsParentFixture.cs | 2 +- NzbDrone.Core/MediaCover/MediaCoverService.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/NzbDrone.Common.Test/DiskProviderTests/IsParentFixture.cs b/NzbDrone.Common.Test/DiskProviderTests/IsParentFixture.cs index a17595a6e0..bc52f482b1 100644 --- a/NzbDrone.Common.Test/DiskProviderTests/IsParentFixture.cs +++ b/NzbDrone.Common.Test/DiskProviderTests/IsParentFixture.cs @@ -34,7 +34,7 @@ public void should_get_free_space_for_drive_that_doesnt_exist() { WindowsOnly(); - Subject.GetAvilableSpace("J:\\").Should().NotBe(0); + Assert.Throws(() => Subject.GetAvilableSpace("J:\\").Should().NotBe(0)); } } } diff --git a/NzbDrone.Core/MediaCover/MediaCoverService.cs b/NzbDrone.Core/MediaCover/MediaCoverService.cs index b14a6bcb30..e3d247bfa7 100644 --- a/NzbDrone.Core/MediaCover/MediaCoverService.cs +++ b/NzbDrone.Core/MediaCover/MediaCoverService.cs @@ -53,7 +53,7 @@ private void EnsureCovers(Series series) } catch (WebException e) { - _logger.Warn(string.Format("Couldn't download media cover for {0}. {1}", series, e.Message); + _logger.Warn(string.Format("Couldn't download media cover for {0}. {1}", series, e.Message)); } catch (Exception e) { From 3e65c393fdceb487dcb8ee397fe58dbf8fc3f34c Mon Sep 17 00:00:00 2001 From: "kay.one" Date: Thu, 29 Aug 2013 19:10:43 -0700 Subject: [PATCH 32/58] fixed broken test --- NzbDrone.Common/PathExtensions.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/NzbDrone.Common/PathExtensions.cs b/NzbDrone.Common/PathExtensions.cs index b5e899eba0..374d2372a4 100644 --- a/NzbDrone.Common/PathExtensions.cs +++ b/NzbDrone.Common/PathExtensions.cs @@ -58,7 +58,15 @@ private static string GetProperCapitalization(DirectoryInfo dirInfo) //Drive letter return dirInfo.Name.ToUpper(); } - return Path.Combine(GetProperCapitalization(parentDirInfo), parentDirInfo.GetDirectories(dirInfo.Name)[0].Name); + + var folderName = dirInfo.Name; + + if (dirInfo.Exists) + { + folderName = parentDirInfo.GetDirectories(dirInfo.Name)[0].Name; + } + + return Path.Combine(GetProperCapitalization(parentDirInfo), folderName); } public static string GetActualCasing(this string path) From 87ac2b3b763ce89f2f439b46795da0a996b8930c Mon Sep 17 00:00:00 2001 From: "kay.one" Date: Thu, 29 Aug 2013 19:27:23 -0700 Subject: [PATCH 33/58] fixed Dtd issues on Linux. --- NzbDrone.Common/Services.cs | 3 --- .../IndexerTests/IntegrationTests/IndexerIntegrationTests.cs | 4 ++-- .../DataAugmentation/DailySeries/DailySeriesDataProxy.cs | 1 - NzbDrone.Core/Indexers/BasicRssParser.cs | 2 +- 4 files changed, 3 insertions(+), 7 deletions(-) diff --git a/NzbDrone.Common/Services.cs b/NzbDrone.Common/Services.cs index bfa5379019..0824c4735e 100644 --- a/NzbDrone.Common/Services.cs +++ b/NzbDrone.Common/Services.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace NzbDrone.Common { diff --git a/NzbDrone.Core.Test/IndexerTests/IntegrationTests/IndexerIntegrationTests.cs b/NzbDrone.Core.Test/IndexerTests/IntegrationTests/IndexerIntegrationTests.cs index d052503a9c..813c1a45f8 100644 --- a/NzbDrone.Core.Test/IndexerTests/IntegrationTests/IndexerIntegrationTests.cs +++ b/NzbDrone.Core.Test/IndexerTests/IntegrationTests/IndexerIntegrationTests.cs @@ -44,17 +44,17 @@ public void wombles_rss() [Test] - [Explicit("needs newznab api key")] public void nzbsorg_rss() { var indexer = new Newznab(); indexer.Settings = new NewznabSettings { - ApiKey = "", + ApiKey = "64d61d3cfd4b75e51d01cbc7c6a78275", Url = "http://nzbs.org" }; indexer.InstanceDefinition = new IndexerDefinition(); + indexer.InstanceDefinition.Name = "nzbs.org"; var result = Subject.FetchRss(indexer); diff --git a/NzbDrone.Core/DataAugmentation/DailySeries/DailySeriesDataProxy.cs b/NzbDrone.Core/DataAugmentation/DailySeries/DailySeriesDataProxy.cs index 239afecc81..f59ff9ee9d 100644 --- a/NzbDrone.Core/DataAugmentation/DailySeries/DailySeriesDataProxy.cs +++ b/NzbDrone.Core/DataAugmentation/DailySeries/DailySeriesDataProxy.cs @@ -3,7 +3,6 @@ using NLog; using NzbDrone.Common; using NzbDrone.Common.Serializer; -using NzbDrone.Core.Configuration; namespace NzbDrone.Core.DataAugmentation.DailySeries { diff --git a/NzbDrone.Core/Indexers/BasicRssParser.cs b/NzbDrone.Core/Indexers/BasicRssParser.cs index 17963956c5..84c61f296d 100644 --- a/NzbDrone.Core/Indexers/BasicRssParser.cs +++ b/NzbDrone.Core/Indexers/BasicRssParser.cs @@ -27,7 +27,7 @@ public BasicRssParser() public IEnumerable Process(string xml, string url) { - using (var xmlTextReader = new XmlTextReader(new StringReader(xml)) { DtdProcessing = DtdProcessing.Ignore }) + using (var xmlTextReader = XmlReader.Create(new StringReader(xml), new XmlReaderSettings { ProhibitDtd = false, IgnoreComments = true })) { var document = XDocument.Load(xmlTextReader); var items = document.Descendants("item"); From b8bd2bffbf133f10e54b2de200f317be0a9af55a Mon Sep 17 00:00:00 2001 From: "kay.one" Date: Thu, 29 Aug 2013 22:20:41 -0700 Subject: [PATCH 34/58] db stores logs for 7 days instead of 15. --- NzbDrone.Core/Instrumentation/LogRepository.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NzbDrone.Core/Instrumentation/LogRepository.cs b/NzbDrone.Core/Instrumentation/LogRepository.cs index 5fe755580e..0a00aa27b5 100644 --- a/NzbDrone.Core/Instrumentation/LogRepository.cs +++ b/NzbDrone.Core/Instrumentation/LogRepository.cs @@ -18,7 +18,7 @@ public LogRepository(IDatabase database, IMessageAggregator messageAggregator) public void Trim() { - var trimDate = DateTime.UtcNow.AddDays(-15).Date; + var trimDate = DateTime.UtcNow.AddDays(-7).Date; Delete(c => c.Time <= trimDate); } } From e256271c5c321cded971867ceb1e467ef43f93f7 Mon Sep 17 00:00:00 2001 From: "kay.one" Date: Thu, 29 Aug 2013 23:38:55 -0700 Subject: [PATCH 35/58] store scene name in history --- .../016_updated_imported_history_item.cs | 14 ++++++++++++++ NzbDrone.Core/History/HistoryService.cs | 15 ++++++++------- .../EpisodeImport/ImportApprovedEpisodes.cs | 6 ++++-- .../MediaFiles/Events/EpisodeImportedEvent.cs | 9 ++++++--- NzbDrone.Core/NzbDrone.Core.csproj | 1 + .../Details/HistoryDetailsViewTemplate.html | 12 ++++++------ 6 files changed, 39 insertions(+), 18 deletions(-) create mode 100644 NzbDrone.Core/Datastore/Migration/016_updated_imported_history_item.cs diff --git a/NzbDrone.Core/Datastore/Migration/016_updated_imported_history_item.cs b/NzbDrone.Core/Datastore/Migration/016_updated_imported_history_item.cs new file mode 100644 index 0000000000..7a2c50e717 --- /dev/null +++ b/NzbDrone.Core/Datastore/Migration/016_updated_imported_history_item.cs @@ -0,0 +1,14 @@ +using FluentMigrator; +using NzbDrone.Core.Datastore.Migration.Framework; + +namespace NzbDrone.Core.Datastore.Migration +{ + [Migration(16)] + public class updated_imported_history_item : NzbDroneMigrationBase + { + protected override void MainDbUpgrade() + { + Execute.Sql(@"UPDATE HISTORY SET Data = replace( Data, '""Path""', '""ImportedPath""' ) WHERE EventType=3"); + } + } +} diff --git a/NzbDrone.Core/History/HistoryService.cs b/NzbDrone.Core/History/HistoryService.cs index 40f637fcfc..349d81c08f 100644 --- a/NzbDrone.Core/History/HistoryService.cs +++ b/NzbDrone.Core/History/HistoryService.cs @@ -62,7 +62,7 @@ public void Handle(EpisodeGrabbedEvent message) { var history = new History { - EventType = HistoryEventType.Grabbed, + EventType = HistoryEventType.Grabbed, Date = DateTime.UtcNow, Quality = message.Episode.ParsedEpisodeInfo.Quality, SourceTitle = message.Episode.Report.Title, @@ -81,20 +81,21 @@ public void Handle(EpisodeGrabbedEvent message) public void Handle(EpisodeImportedEvent message) { - foreach (var episode in message.EpisodeFile.Episodes.Value) + foreach (var episode in message.DroppedEpisode.Episodes) { var history = new History { EventType = HistoryEventType.DownloadFolderImported, Date = DateTime.UtcNow, - Quality = message.EpisodeFile.Quality, - SourceTitle = message.EpisodeFile.Path, - SeriesId = message.EpisodeFile.SeriesId, + Quality = message.DroppedEpisode.Quality, + SourceTitle = message.ImportedEpisode.SceneName, + SeriesId = message.ImportedEpisode.SeriesId, EpisodeId = episode.Id }; - history.Data.Add("Path", message.EpisodeFile.Path); - history.Data.Add("Filename", Path.GetFileNameWithoutExtension(message.EpisodeFile.Path)); + history.Data.Add("FileId", message.ImportedEpisode.Id.ToString()); + history.Data.Add("DroppedPath", message.DroppedEpisode.Path); + history.Data.Add("ImportedPath", message.ImportedEpisode.Path); _historyRepository.Insert(history); } diff --git a/NzbDrone.Core/MediaFiles/EpisodeImport/ImportApprovedEpisodes.cs b/NzbDrone.Core/MediaFiles/EpisodeImport/ImportApprovedEpisodes.cs index 0757b14956..539bb8ccd6 100644 --- a/NzbDrone.Core/MediaFiles/EpisodeImport/ImportApprovedEpisodes.cs +++ b/NzbDrone.Core/MediaFiles/EpisodeImport/ImportApprovedEpisodes.cs @@ -65,12 +65,14 @@ public List Import(List decisions, bool newDownl episodeFile.SceneName = Path.GetFileNameWithoutExtension(localEpisode.Path.CleanFilePath()); episodeFile.Episodes = localEpisode.Episodes; + if (newDownload) { episodeFile = _episodeFileUpgrader.UpgradeEpisodeFile(episodeFile, localEpisode); - _messageAggregator.PublishEvent(new EpisodeImportedEvent(episodeFile)); + _messageAggregator.PublishEvent(new EpisodeImportedEvent(localEpisode, episodeFile)); } - + + _mediaFileService.Add(episodeFile); imported.Add(importDecision); } diff --git a/NzbDrone.Core/MediaFiles/Events/EpisodeImportedEvent.cs b/NzbDrone.Core/MediaFiles/Events/EpisodeImportedEvent.cs index 9c8e59cdc9..2f166b069f 100644 --- a/NzbDrone.Core/MediaFiles/Events/EpisodeImportedEvent.cs +++ b/NzbDrone.Core/MediaFiles/Events/EpisodeImportedEvent.cs @@ -1,14 +1,17 @@ using NzbDrone.Common.Messaging; +using NzbDrone.Core.Parser.Model; namespace NzbDrone.Core.MediaFiles.Events { public class EpisodeImportedEvent : IEvent { - public EpisodeFile EpisodeFile { get; private set; } + public LocalEpisode DroppedEpisode { get; private set; } + public EpisodeFile ImportedEpisode { get; private set; } - public EpisodeImportedEvent(EpisodeFile episodeFile) + public EpisodeImportedEvent(LocalEpisode droppedEpisode, EpisodeFile importedEpisode) { - EpisodeFile = episodeFile; + DroppedEpisode = droppedEpisode; + ImportedEpisode = importedEpisode; } } } \ No newline at end of file diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index 9ed55a6ff0..26f5df9b86 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -158,6 +158,7 @@ + diff --git a/UI/History/Details/HistoryDetailsViewTemplate.html b/UI/History/Details/HistoryDetailsViewTemplate.html index 832573e9ea..5d15ca7b40 100644 --- a/UI/History/Details/HistoryDetailsViewTemplate.html +++ b/UI/History/Details/HistoryDetailsViewTemplate.html @@ -35,14 +35,14 @@ {{#if data}} {{#with data}}
- {{#if filename}} -
Filename
-
{{filename}}
+ {{#if droppedPath}} +
Source:
+
{{droppedPath}}
{{/if}} - {{#if path}} -
Path
-
{{path}}
+ {{#if importedPath}} +
Imported To:
+
{{importedPath}}
{{/if}}
{{/with}} From 954a79639fc5cf15b758a0e3ec4d7298a7c55e15 Mon Sep 17 00:00:00 2001 From: "kay.one" Date: Thu, 29 Aug 2013 23:39:41 -0700 Subject: [PATCH 36/58] moveepisode is less side-effecty! --- .../ImportApprovedEpisodesFixture.cs | 3 +-- .../RenameEpisodeFileServiceFixture.cs | 3 +-- NzbDrone.Core/History/HistoryService.cs | 3 ++- .../MediaFiles/EpisodeFileMovingService.cs | 27 +++++++------------ .../EpisodeImport/ImportApprovedEpisodes.cs | 6 ++--- .../MediaFiles/UpgradeMediaFileService.cs | 4 +-- 6 files changed, 19 insertions(+), 27 deletions(-) diff --git a/NzbDrone.Core.Test/MediaFileTests/ImportApprovedEpisodesFixture.cs b/NzbDrone.Core.Test/MediaFileTests/ImportApprovedEpisodesFixture.cs index 9e34a5882a..a7d13ff0c3 100644 --- a/NzbDrone.Core.Test/MediaFileTests/ImportApprovedEpisodesFixture.cs +++ b/NzbDrone.Core.Test/MediaFileTests/ImportApprovedEpisodesFixture.cs @@ -53,8 +53,7 @@ public void Setup() } Mocker.GetMock() - .Setup(s => s.UpgradeEpisodeFile(It.IsAny(), It.IsAny())) - .Returns(new EpisodeFile()); + .Setup(s => s.UpgradeEpisodeFile(It.IsAny(), It.IsAny())); } [Test] diff --git a/NzbDrone.Core.Test/MediaFileTests/RenameEpisodeFileServiceFixture.cs b/NzbDrone.Core.Test/MediaFileTests/RenameEpisodeFileServiceFixture.cs index dbdf35b561..80b4dc855e 100644 --- a/NzbDrone.Core.Test/MediaFileTests/RenameEpisodeFileServiceFixture.cs +++ b/NzbDrone.Core.Test/MediaFileTests/RenameEpisodeFileServiceFixture.cs @@ -60,8 +60,7 @@ private void GivenEpisodeFiles() private void GivenMovedFiles() { Mocker.GetMock() - .Setup(s => s.MoveEpisodeFile(It.IsAny(), _series)) - .Returns(_episodeFiles.First()); + .Setup(s => s.MoveEpisodeFile(It.IsAny(), _series)); } [Test] diff --git a/NzbDrone.Core/History/HistoryService.cs b/NzbDrone.Core/History/HistoryService.cs index 349d81c08f..c0752eb2a1 100644 --- a/NzbDrone.Core/History/HistoryService.cs +++ b/NzbDrone.Core/History/HistoryService.cs @@ -93,7 +93,8 @@ public void Handle(EpisodeImportedEvent message) EpisodeId = episode.Id }; - history.Data.Add("FileId", message.ImportedEpisode.Id.ToString()); + //Won't have a value since we publish this event before saving to DB. + //history.Data.Add("FileId", message.ImportedEpisode.Id.ToString()); history.Data.Add("DroppedPath", message.DroppedEpisode.Path); history.Data.Add("ImportedPath", message.ImportedEpisode.Path); diff --git a/NzbDrone.Core/MediaFiles/EpisodeFileMovingService.cs b/NzbDrone.Core/MediaFiles/EpisodeFileMovingService.cs index e46bf3b26e..e7a03d22ac 100644 --- a/NzbDrone.Core/MediaFiles/EpisodeFileMovingService.cs +++ b/NzbDrone.Core/MediaFiles/EpisodeFileMovingService.cs @@ -13,8 +13,8 @@ namespace NzbDrone.Core.MediaFiles { public interface IMoveEpisodeFiles { - EpisodeFile MoveEpisodeFile(EpisodeFile episodeFile, Series series); - EpisodeFile MoveEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode); + string MoveEpisodeFile(EpisodeFile episodeFile, Series series); + string MoveEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode); } public class MoveEpisodeFiles : IMoveEpisodeFiles @@ -38,27 +38,24 @@ public MoveEpisodeFiles(IEpisodeService episodeService, _logger = logger; } - public EpisodeFile MoveEpisodeFile(EpisodeFile episodeFile, Series series) + public string MoveEpisodeFile(EpisodeFile episodeFile, Series series) { var episodes = _episodeService.GetEpisodesByFileId(episodeFile.Id); var newFileName = _buildFileNames.BuildFilename(episodes, series, episodeFile); - var destinationFilename = _buildFileNames.BuildFilePath(series, episodes.First().SeasonNumber, newFileName, Path.GetExtension(episodeFile.Path)); + var filePath = _buildFileNames.BuildFilePath(series, episodes.First().SeasonNumber, newFileName, Path.GetExtension(episodeFile.Path)); - return MoveFile(episodeFile, destinationFilename); + return filePath; } - public EpisodeFile MoveEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode) + public string MoveEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode) { var newFileName = _buildFileNames.BuildFilename(localEpisode.Episodes, localEpisode.Series, episodeFile); - var destinationFilename = _buildFileNames.BuildFilePath(localEpisode.Series, localEpisode.SeasonNumber, newFileName, Path.GetExtension(episodeFile.Path)); - episodeFile = MoveFile(episodeFile, destinationFilename); - - _messageAggregator.PublishEvent(new EpisodeDownloadedEvent(localEpisode)); - - return episodeFile; + var filePath = _buildFileNames.BuildFilePath(localEpisode.Series, localEpisode.SeasonNumber, newFileName, Path.GetExtension(episodeFile.Path)); + MoveFile(episodeFile, filePath); + return filePath; } - private EpisodeFile MoveFile(EpisodeFile episodeFile, string destinationFilename) + private void MoveFile(EpisodeFile episodeFile, string destinationFilename) { if (!_diskProvider.FileExists(episodeFile.Path)) { @@ -85,10 +82,6 @@ private EpisodeFile MoveFile(EpisodeFile episodeFile, string destinationFilename _logger.Debug("Unable to apply folder permissions to: ", destinationFilename); _logger.TraceException(ex.Message, ex); } - - episodeFile.Path = destinationFilename; - - return episodeFile; } } } \ No newline at end of file diff --git a/NzbDrone.Core/MediaFiles/EpisodeImport/ImportApprovedEpisodes.cs b/NzbDrone.Core/MediaFiles/EpisodeImport/ImportApprovedEpisodes.cs index 539bb8ccd6..087f29e681 100644 --- a/NzbDrone.Core/MediaFiles/EpisodeImport/ImportApprovedEpisodes.cs +++ b/NzbDrone.Core/MediaFiles/EpisodeImport/ImportApprovedEpisodes.cs @@ -13,7 +13,7 @@ public interface IImportApprovedEpisodes { List Import(List decisions, bool newDownloads = false); } - + public class ImportApprovedEpisodes : IImportApprovedEpisodes { private readonly IUpgradeMediaFiles _episodeFileUpgrader; @@ -68,10 +68,10 @@ public List Import(List decisions, bool newDownl if (newDownload) { - episodeFile = _episodeFileUpgrader.UpgradeEpisodeFile(episodeFile, localEpisode); + episodeFile.Path = _episodeFileUpgrader.UpgradeEpisodeFile(episodeFile, localEpisode); _messageAggregator.PublishEvent(new EpisodeImportedEvent(localEpisode, episodeFile)); + _messageAggregator.PublishEvent(new EpisodeDownloadedEvent(localEpisode)); } - _mediaFileService.Add(episodeFile); imported.Add(importDecision); diff --git a/NzbDrone.Core/MediaFiles/UpgradeMediaFileService.cs b/NzbDrone.Core/MediaFiles/UpgradeMediaFileService.cs index c272e91977..75ee6869ee 100644 --- a/NzbDrone.Core/MediaFiles/UpgradeMediaFileService.cs +++ b/NzbDrone.Core/MediaFiles/UpgradeMediaFileService.cs @@ -7,7 +7,7 @@ namespace NzbDrone.Core.MediaFiles { public interface IUpgradeMediaFiles { - EpisodeFile UpgradeEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode); + string UpgradeEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode); } public class UpgradeMediaFileService : IUpgradeMediaFiles @@ -31,7 +31,7 @@ public UpgradeMediaFileService(IRecycleBinProvider recycleBinProvider, _logger = logger; } - public EpisodeFile UpgradeEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode) + public string UpgradeEpisodeFile(EpisodeFile episodeFile, LocalEpisode localEpisode) { var existingFiles = localEpisode.Episodes .Where(e => e.EpisodeFileId > 0) From c25b92955f0fd68ba66d6b235db8823488eab172 Mon Sep 17 00:00:00 2001 From: "kay.one" Date: Thu, 29 Aug 2013 23:41:49 -0700 Subject: [PATCH 37/58] moveepisode is less side-effecty! --- NzbDrone.Core/MediaFiles/RenameEpisodeFileService.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/NzbDrone.Core/MediaFiles/RenameEpisodeFileService.cs b/NzbDrone.Core/MediaFiles/RenameEpisodeFileService.cs index f6737a9ef9..7912039e71 100644 --- a/NzbDrone.Core/MediaFiles/RenameEpisodeFileService.cs +++ b/NzbDrone.Core/MediaFiles/RenameEpisodeFileService.cs @@ -34,14 +34,12 @@ private void RenameFiles(List episodeFiles, Series series) { var renamed = new List(); - foreach (var file in episodeFiles) + foreach (var episodeFile in episodeFiles) { try { - var episodeFile = file; - _logger.Trace("Renaming episode file: {0}", episodeFile); - episodeFile = _episodeFileMover.MoveEpisodeFile(episodeFile, series); + episodeFile.Path = _episodeFileMover.MoveEpisodeFile(episodeFile, series); _mediaFileService.Update(episodeFile); renamed.Add(episodeFile); @@ -54,7 +52,7 @@ private void RenameFiles(List episodeFiles, Series series) } catch (Exception ex) { - _logger.ErrorException("Failed to rename file: " + file.Path, ex); + _logger.ErrorException("Failed to rename file: " + episodeFile.Path, ex); } } From dd835d55033c7cdf5c4e279cb56635631b4b84b9 Mon Sep 17 00:00:00 2001 From: "kay.one" Date: Thu, 29 Aug 2013 23:50:43 -0700 Subject: [PATCH 38/58] clear existing scene name since it wasn't storing the correct string --- .../Datastore/Migration/017_reset_scene_names.cs | 15 +++++++++++++++ .../EpisodeImport/ImportApprovedEpisodes.cs | 2 +- NzbDrone.Core/NzbDrone.Core.csproj | 1 + 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 NzbDrone.Core/Datastore/Migration/017_reset_scene_names.cs diff --git a/NzbDrone.Core/Datastore/Migration/017_reset_scene_names.cs b/NzbDrone.Core/Datastore/Migration/017_reset_scene_names.cs new file mode 100644 index 0000000000..e2e3a21d66 --- /dev/null +++ b/NzbDrone.Core/Datastore/Migration/017_reset_scene_names.cs @@ -0,0 +1,15 @@ +using FluentMigrator; +using NzbDrone.Core.Datastore.Migration.Framework; + +namespace NzbDrone.Core.Datastore.Migration +{ + [Migration(17)] + public class reset_scene_names : NzbDroneMigrationBase + { + protected override void MainDbUpgrade() + { + //we were storing new file name as scene name. + Execute.Sql(@"UPDATE EpisodeFiles SET SceneName = NULL where SceneName != NULL"); + } + } +} diff --git a/NzbDrone.Core/MediaFiles/EpisodeImport/ImportApprovedEpisodes.cs b/NzbDrone.Core/MediaFiles/EpisodeImport/ImportApprovedEpisodes.cs index 087f29e681..733b8580d4 100644 --- a/NzbDrone.Core/MediaFiles/EpisodeImport/ImportApprovedEpisodes.cs +++ b/NzbDrone.Core/MediaFiles/EpisodeImport/ImportApprovedEpisodes.cs @@ -62,12 +62,12 @@ public List Import(List decisions, bool newDownl episodeFile.Size = _diskProvider.GetFileSize(localEpisode.Path); episodeFile.Quality = localEpisode.Quality; episodeFile.SeasonNumber = localEpisode.SeasonNumber; - episodeFile.SceneName = Path.GetFileNameWithoutExtension(localEpisode.Path.CleanFilePath()); episodeFile.Episodes = localEpisode.Episodes; if (newDownload) { + episodeFile.SceneName = Path.GetFileNameWithoutExtension(localEpisode.Path.CleanFilePath()); episodeFile.Path = _episodeFileUpgrader.UpgradeEpisodeFile(episodeFile, localEpisode); _messageAggregator.PublishEvent(new EpisodeImportedEvent(localEpisode, episodeFile)); _messageAggregator.PublishEvent(new EpisodeDownloadedEvent(localEpisode)); diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index 26f5df9b86..82fd0aa608 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -159,6 +159,7 @@ + From 7a19b6a2b3af7ca988a5111773b870641db0fe1b Mon Sep 17 00:00:00 2001 From: Keivan Beigi Date: Fri, 30 Aug 2013 15:55:01 -0700 Subject: [PATCH 39/58] Host process cleanup. --- NzbDrone.Console/ConsoleApp.cs | 5 ++- .../AccessControl/FirewallAdapter.cs | 38 ++----------------- NzbDrone.Host/AccessControl/UrlAclAdapter.cs | 16 ++++++-- NzbDrone.Host/ApplicationServer.cs | 13 +------ NzbDrone.Host/Owin/IHostController.cs | 1 - NzbDrone.Host/Owin/OwinHostController.cs | 29 ++++++++------ NzbDrone/NzbDrone.csproj | 4 ++ NzbDrone/WindowsApp.cs | 4 ++ NzbDrone/packages.config | 1 + 9 files changed, 46 insertions(+), 65 deletions(-) diff --git a/NzbDrone.Console/ConsoleApp.cs b/NzbDrone.Console/ConsoleApp.cs index 586027a54c..726139f8ae 100644 --- a/NzbDrone.Console/ConsoleApp.cs +++ b/NzbDrone.Console/ConsoleApp.cs @@ -1,5 +1,6 @@ using System; using System.Threading; +using NLog; using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Host; @@ -7,6 +8,8 @@ namespace NzbDrone.Console { public static class ConsoleApp { + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + public static void Main(string[] args) { try @@ -18,7 +21,7 @@ public static void Main(string[] args) } catch (Exception e) { - System.Console.WriteLine(e.ToString()); + Logger.FatalException(e.Message, e); System.Console.ReadLine(); } diff --git a/NzbDrone.Host/AccessControl/FirewallAdapter.cs b/NzbDrone.Host/AccessControl/FirewallAdapter.cs index 96fb876795..72d1944467 100644 --- a/NzbDrone.Host/AccessControl/FirewallAdapter.cs +++ b/NzbDrone.Host/AccessControl/FirewallAdapter.cs @@ -1,6 +1,7 @@ using System; using NetFwTypeLib; using NLog; +using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Core.Configuration; namespace NzbDrone.Host.AccessControl @@ -31,9 +32,6 @@ public void MakeAccessible() return; } - CloseFirewallPort(); - - //Open the new port OpenFirewallPort(_configFileProvider.Port); } } @@ -91,38 +89,10 @@ private void OpenFirewallPort(int portNumber) } } - private void CloseFirewallPort() - { - try - { - var netFwMgrType = Type.GetTypeFromProgID("HNetCfg.FwMgr", false); - var mgr = (INetFwMgr)Activator.CreateInstance(netFwMgrType); - var ports = mgr.LocalPolicy.CurrentProfile.GloballyOpenPorts; - - var portNumber = 8989; - - foreach (INetFwOpenPort p in ports) - { - if (p.Name == "NzbDrone") - { - portNumber = p.Port; - break; - } - } - - if (portNumber != _configFileProvider.Port) - { - ports.Remove(portNumber, NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP); - } - } - catch (Exception ex) - { - _logger.WarnException("Failed to close port in firewall for NzbDrone", ex); - } - } - private bool IsFirewallEnabled() { + if (OsInfo.IsLinux) return false; + try { var netFwMgrType = Type.GetTypeFromProgID("HNetCfg.FwMgr", false); @@ -135,7 +105,5 @@ private bool IsFirewallEnabled() return false; } } - - } } diff --git a/NzbDrone.Host/AccessControl/UrlAclAdapter.cs b/NzbDrone.Host/AccessControl/UrlAclAdapter.cs index c7e1480d64..e536fffbd0 100644 --- a/NzbDrone.Host/AccessControl/UrlAclAdapter.cs +++ b/NzbDrone.Host/AccessControl/UrlAclAdapter.cs @@ -9,6 +9,7 @@ namespace NzbDrone.Host.AccessControl public interface IUrlAclAdapter { void RefreshRegistration(); + string UrlAcl { get; } } public class UrlAclAdapter : IUrlAclAdapter @@ -24,18 +25,25 @@ public UrlAclAdapter(IProcessProvider processProvider, IConfigFileProvider confi _logger = logger; } + public string UrlAcl + { + get + { + return "http://*:" + _configFileProvider.Port + "/"; + } + } + public void RefreshRegistration() { if (OsInfo.Version.Major < 6) return; - RegisterUrl(_configFileProvider.Port); + RegisterUrl(); } - - private void RegisterUrl(int portNumber) + private void RegisterUrl() { - var arguments = String.Format("http add urlacl http://*:{0}/ sddl=D:(A;;GX;;;S-1-1-0)", portNumber); + var arguments = String.Format("http add urlacl {0} sddl=D:(A;;GX;;;S-1-1-0)", UrlAcl); RunNetsh(arguments); } diff --git a/NzbDrone.Host/ApplicationServer.cs b/NzbDrone.Host/ApplicationServer.cs index b1abc00c57..d6e1e36259 100644 --- a/NzbDrone.Host/ApplicationServer.cs +++ b/NzbDrone.Host/ApplicationServer.cs @@ -4,7 +4,6 @@ using NzbDrone.Common; using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Core.Configuration; -using NzbDrone.Host.AccessControl; using NzbDrone.Host.Owin; namespace NzbDrone.Host @@ -23,13 +22,10 @@ public class NzbDroneServiceFactory : ServiceBase, INzbDroneServiceFactory private readonly IProcessProvider _processProvider; private readonly PriorityMonitor _priorityMonitor; private readonly IStartupArguments _startupArguments; - private readonly IFirewallAdapter _firewallAdapter; - private readonly IUrlAclAdapter _urlAclAdapter; private readonly Logger _logger; public NzbDroneServiceFactory(IConfigFileProvider configFileProvider, IHostController hostController, IRuntimeInfo runtimeInfo, - IProcessProvider processProvider, PriorityMonitor priorityMonitor, IStartupArguments startupArguments, - IFirewallAdapter firewallAdapter, IUrlAclAdapter urlAclAdapter, Logger logger) + IProcessProvider processProvider, PriorityMonitor priorityMonitor, IStartupArguments startupArguments, Logger logger) { _configFileProvider = configFileProvider; _hostController = hostController; @@ -37,8 +33,6 @@ public NzbDroneServiceFactory(IConfigFileProvider configFileProvider, IHostContr _processProvider = processProvider; _priorityMonitor = priorityMonitor; _startupArguments = startupArguments; - _firewallAdapter = firewallAdapter; - _urlAclAdapter = urlAclAdapter; _logger = logger; } @@ -49,11 +43,6 @@ protected override void OnStart(string[] args) public void Start() { - if (OsInfo.IsWindows && _runtimeInfo.IsAdmin) - { - _urlAclAdapter.RefreshRegistration(); - _firewallAdapter.MakeAccessible(); - } _hostController.StartServer(); if (!_startupArguments.Flags.Contains(StartupArguments.NO_BROWSER) && diff --git a/NzbDrone.Host/Owin/IHostController.cs b/NzbDrone.Host/Owin/IHostController.cs index 9df77feb49..026bff89e5 100644 --- a/NzbDrone.Host/Owin/IHostController.cs +++ b/NzbDrone.Host/Owin/IHostController.cs @@ -4,7 +4,6 @@ public interface IHostController { string AppUrl { get; } void StartServer(); - void RestartServer(); void StopServer(); } } \ No newline at end of file diff --git a/NzbDrone.Host/Owin/OwinHostController.cs b/NzbDrone.Host/Owin/OwinHostController.cs index a571d55304..9968b22bb2 100644 --- a/NzbDrone.Host/Owin/OwinHostController.cs +++ b/NzbDrone.Host/Owin/OwinHostController.cs @@ -3,8 +3,10 @@ using System.Linq; using Microsoft.Owin.Hosting; using NLog; +using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.Security; using NzbDrone.Core.Configuration; +using NzbDrone.Host.AccessControl; using NzbDrone.Host.Owin.MiddleWare; using Owin; @@ -14,13 +16,20 @@ public class OwinHostController : IHostController { private readonly IConfigFileProvider _configFileProvider; private readonly IEnumerable _owinMiddleWares; + private readonly IRuntimeInfo _runtimeInfo; + private readonly IUrlAclAdapter _urlAclAdapter; + private readonly IFirewallAdapter _firewallAdapter; private readonly Logger _logger; private IDisposable _host; - public OwinHostController(IConfigFileProvider configFileProvider, IEnumerable owinMiddleWares, Logger logger) + public OwinHostController(IConfigFileProvider configFileProvider, IEnumerable owinMiddleWares, + IRuntimeInfo runtimeInfo, IUrlAclAdapter urlAclAdapter, IFirewallAdapter firewallAdapter, Logger logger) { _configFileProvider = configFileProvider; _owinMiddleWares = owinMiddleWares; + _runtimeInfo = runtimeInfo; + _urlAclAdapter = urlAclAdapter; + _firewallAdapter = firewallAdapter; _logger = logger; } @@ -28,14 +37,18 @@ public void StartServer() { IgnoreCertErrorPolicy.Register(); - var url = "http://*:" + _configFileProvider.Port; + if (OsInfo.IsWindows && _runtimeInfo.IsAdmin) + { + _urlAclAdapter.RefreshRegistration(); + _firewallAdapter.MakeAccessible(); + } - var options = new StartOptions(url) + var options = new StartOptions(_urlAclAdapter.UrlAcl) { ServerFactory = "Microsoft.Owin.Host.HttpListener" }; - _logger.Info("starting server on {0}", url); + _logger.Info("starting server on {0}", _urlAclAdapter.UrlAcl); _host = WebApp.Start(OwinServiceProviderFactory.Create(), options, BuildApp); } @@ -56,14 +69,6 @@ public string AppUrl get { return string.Format("http://localhost:{0}", _configFileProvider.Port); } } - public void RestartServer() - { - _logger.Warn("Attempting to restart server."); - - StopServer(); - StartServer(); - } - public void StopServer() { if (_host == null) return; diff --git a/NzbDrone/NzbDrone.csproj b/NzbDrone/NzbDrone.csproj index b599ed47b0..5d45930cd6 100644 --- a/NzbDrone/NzbDrone.csproj +++ b/NzbDrone/NzbDrone.csproj @@ -83,6 +83,10 @@ False ..\packages\Newtonsoft.Json.5.0.6\lib\net40\Newtonsoft.Json.dll
+ + False + ..\packages\NLog.2.0.1.2\lib\net40\NLog.dll + False ..\packages\Owin.1.0\lib\net40\Owin.dll diff --git a/NzbDrone/WindowsApp.cs b/NzbDrone/WindowsApp.cs index 0ded14d614..e144b82cce 100644 --- a/NzbDrone/WindowsApp.cs +++ b/NzbDrone/WindowsApp.cs @@ -1,5 +1,6 @@ using System; using System.Windows.Forms; +using NLog; using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Host; using NzbDrone.SysTray; @@ -8,6 +9,8 @@ namespace NzbDrone { public static class WindowsApp { + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + public static void Main(string[] args) { try @@ -21,6 +24,7 @@ public static void Main(string[] args) } catch (Exception e) { + Logger.FatalException(e.Message, e); var message = string.Format("{0}: {1}", e.GetType().Name, e.Message); MessageBox.Show(text: message, buttons: MessageBoxButtons.OK, icon: MessageBoxIcon.Error, caption: "Epic Fail!"); } diff --git a/NzbDrone/packages.config b/NzbDrone/packages.config index 907d39c5ab..19f3a3d8bb 100644 --- a/NzbDrone/packages.config +++ b/NzbDrone/packages.config @@ -5,5 +5,6 @@ + \ No newline at end of file From 298d6fe3bf3d457c398b61b2682b789ed73313f6 Mon Sep 17 00:00:00 2001 From: Keivan Beigi Date: Fri, 30 Aug 2013 19:45:44 -0700 Subject: [PATCH 40/58] fixed app startup --- NzbDrone.Console/ConsoleApp.cs | 3 --- NzbDrone/WindowsApp.cs | 2 -- 2 files changed, 5 deletions(-) diff --git a/NzbDrone.Console/ConsoleApp.cs b/NzbDrone.Console/ConsoleApp.cs index 726139f8ae..3119cc811a 100644 --- a/NzbDrone.Console/ConsoleApp.cs +++ b/NzbDrone.Console/ConsoleApp.cs @@ -8,8 +8,6 @@ namespace NzbDrone.Console { public static class ConsoleApp { - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - public static void Main(string[] args) { try @@ -21,7 +19,6 @@ public static void Main(string[] args) } catch (Exception e) { - Logger.FatalException(e.Message, e); System.Console.ReadLine(); } diff --git a/NzbDrone/WindowsApp.cs b/NzbDrone/WindowsApp.cs index e144b82cce..4d4dc9d69a 100644 --- a/NzbDrone/WindowsApp.cs +++ b/NzbDrone/WindowsApp.cs @@ -9,7 +9,6 @@ namespace NzbDrone { public static class WindowsApp { - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); public static void Main(string[] args) { @@ -24,7 +23,6 @@ public static void Main(string[] args) } catch (Exception e) { - Logger.FatalException(e.Message, e); var message = string.Format("{0}: {1}", e.GetType().Name, e.Message); MessageBox.Show(text: message, buttons: MessageBoxButtons.OK, icon: MessageBoxIcon.Error, caption: "Epic Fail!"); } From 4ffcf6b8c6a678c29102e0b652f288786e25b426 Mon Sep 17 00:00:00 2001 From: Keivan Beigi Date: Fri, 30 Aug 2013 23:10:08 -0700 Subject: [PATCH 41/58] updated deb control file. --- debian/control | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/debian/control b/debian/control index ed77723aec..32d1ac5491 100644 --- a/debian/control +++ b/debian/control @@ -1,12 +1,11 @@ -Source: nzbdrone +Package: nzbdrone Section: web Priority: optional -Maintainer: NzbDrone Depends: libmono-cil-dev (>= 2.10.1) +Architecture: all +Maintainer: NzbDrone +Source: nzbdrone Homepage: http://www.nzbdrone.com Vcs-Git: git@github.com:NzbDrone/NzbDrone.git Vcs-Browser: https://github.com/NzbDrone/NzbDrone - -Package: nzbdrone -Architecture: all Description: NZBDrone is a PVR for newsgroup users From a4d92f0a31f0e7bdd411bafddc7aa1fe9e09dcfb Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Fri, 30 Aug 2013 23:25:31 -0700 Subject: [PATCH 42/58] Removed tooltip for quality profile name --- UI/Settings/Quality/Profile/EditQualityProfileTemplate.html | 3 --- 1 file changed, 3 deletions(-) diff --git a/UI/Settings/Quality/Profile/EditQualityProfileTemplate.html b/UI/Settings/Quality/Profile/EditQualityProfileTemplate.html index 021a494d7b..f45c97dda2 100644 --- a/UI/Settings/Quality/Profile/EditQualityProfileTemplate.html +++ b/UI/Settings/Quality/Profile/EditQualityProfileTemplate.html @@ -12,9 +12,6 @@
- - -
From 8a71621de7f165261ddbfe4067d43bc0ffa3a0ca Mon Sep 17 00:00:00 2001 From: Keivan Beigi Date: Fri, 30 Aug 2013 23:26:33 -0700 Subject: [PATCH 43/58] Update control --- debian/control | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/debian/control b/debian/control index 32d1ac5491..d6e75940e4 100644 --- a/debian/control +++ b/debian/control @@ -1,11 +1,13 @@ -Package: nzbdrone Section: web Priority: optional -Depends: libmono-cil-dev (>= 2.10.1) -Architecture: all Maintainer: NzbDrone Source: nzbdrone Homepage: http://www.nzbdrone.com Vcs-Git: git@github.com:NzbDrone/NzbDrone.git Vcs-Browser: https://github.com/NzbDrone/NzbDrone + + +Package: nzbdrone +Architecture: all +Depends: libmono-cil-dev (>= 2.10.1) Description: NZBDrone is a PVR for newsgroup users From bf9946b6538e1c3a81edda8f9473160623183d84 Mon Sep 17 00:00:00 2001 From: Keivan Beigi Date: Fri, 30 Aug 2013 23:26:51 -0700 Subject: [PATCH 44/58] Update control --- debian/control | 1 - 1 file changed, 1 deletion(-) diff --git a/debian/control b/debian/control index d6e75940e4..e7f6a7b11d 100644 --- a/debian/control +++ b/debian/control @@ -6,7 +6,6 @@ Homepage: http://www.nzbdrone.com Vcs-Git: git@github.com:NzbDrone/NzbDrone.git Vcs-Browser: https://github.com/NzbDrone/NzbDrone - Package: nzbdrone Architecture: all Depends: libmono-cil-dev (>= 2.10.1) From 4465d50a317694d7224ccafb454701f2629294f8 Mon Sep 17 00:00:00 2001 From: "kay.one" Date: Sat, 31 Aug 2013 13:31:58 -0700 Subject: [PATCH 45/58] added path validation to add series/ recent folders. --- NzbDrone.Api/NzbDrone.Api.csproj | 1 + NzbDrone.Api/RootFolders/RootFolderModule.cs | 3 + NzbDrone.Api/Series/SeriesModule.cs | 6 +- NzbDrone.Api/Validation/PathValidator.cs | 18 +++++ .../Validation/RuleBuilderExtensions.cs | 9 ++- .../EnsureThat/EnsureStringExtensions.cs | 30 ++------ NzbDrone.Common/PathExtensions.cs | 27 +++++++ .../Validation/RuleBuilderExtensions.cs | 1 + NzbDrone.Integration.Test/IntegrationTest.cs | 7 +- .../RootFolderIntegrationTest.cs | 12 ++++ .../SeriesIntegrationTest.cs | 6 -- UI/AddSeries/RootFolders/Collection.js | 2 +- UI/AddSeries/RootFolders/Layout.js | 11 ++- UI/AddSeries/RootFolders/LayoutTemplate.html | 9 ++- UI/AddSeries/RootFolders/Model.js | 1 + UI/AddSeries/SearchResultView.js | 3 +- UI/Content/theme.less | 11 +-- UI/Mixins/AsValidatedView.js | 70 +++++++++---------- UI/jQuery/jquery.validation.js | 7 +- 19 files changed, 146 insertions(+), 88 deletions(-) create mode 100644 NzbDrone.Api/Validation/PathValidator.cs diff --git a/NzbDrone.Api/NzbDrone.Api.csproj b/NzbDrone.Api/NzbDrone.Api.csproj index 5210ef0a60..d0a03bd178 100644 --- a/NzbDrone.Api/NzbDrone.Api.csproj +++ b/NzbDrone.Api/NzbDrone.Api.csproj @@ -164,6 +164,7 @@ + diff --git a/NzbDrone.Api/RootFolders/RootFolderModule.cs b/NzbDrone.Api/RootFolders/RootFolderModule.cs index 5c13a736c2..7bcc4aa52e 100644 --- a/NzbDrone.Api/RootFolders/RootFolderModule.cs +++ b/NzbDrone.Api/RootFolders/RootFolderModule.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using NzbDrone.Core.RootFolders; using NzbDrone.Api.Mapping; +using NzbDrone.Api.Validation; namespace NzbDrone.Api.RootFolders { @@ -17,6 +18,8 @@ public RootFolderModule(IRootFolderService rootFolderService) GetResourceById = GetRootFolder; CreateResource = CreateRootFolder; DeleteResource = DeleteFolder; + + SharedValidator.RuleFor(c=>c.Path).IsValidPath(); } private RootFolderResource GetRootFolder(int id) diff --git a/NzbDrone.Api/Series/SeriesModule.cs b/NzbDrone.Api/Series/SeriesModule.cs index 57caeb7a63..fe7b820a6e 100644 --- a/NzbDrone.Api/Series/SeriesModule.cs +++ b/NzbDrone.Api/Series/SeriesModule.cs @@ -31,10 +31,10 @@ public SeriesModule(ISeriesService seriesService, ISeriesStatisticsService serie SharedValidator.RuleFor(s => s.QualityProfileId).ValidId(); - PutValidator.RuleFor(s => s.Path).NotEmpty(); + PutValidator.RuleFor(s => s.Path).IsValidPath(); - PostValidator.RuleFor(s => s.Path).NotEmpty().When(s => String.IsNullOrEmpty(s.RootFolderPath)); - PostValidator.RuleFor(s => s.RootFolderPath).NotEmpty().When(s => String.IsNullOrEmpty(s.Path)); + PostValidator.RuleFor(s => s.Path).IsValidPath().When(s => String.IsNullOrEmpty(s.RootFolderPath)); + PostValidator.RuleFor(s => s.RootFolderPath).IsValidPath().When(s => String.IsNullOrEmpty(s.Path)); PostValidator.RuleFor(s => s.Title).NotEmpty(); } diff --git a/NzbDrone.Api/Validation/PathValidator.cs b/NzbDrone.Api/Validation/PathValidator.cs new file mode 100644 index 0000000000..bc055a98ce --- /dev/null +++ b/NzbDrone.Api/Validation/PathValidator.cs @@ -0,0 +1,18 @@ +using FluentValidation.Validators; +using NzbDrone.Common; + +namespace NzbDrone.Api.Validation +{ + public class PathValidator : PropertyValidator + { + public PathValidator() + : base("Invalid Path") + { + } + + protected override bool IsValid(PropertyValidatorContext context) + { + return context.PropertyValue.ToString().IsPathValid(); + } + } +} \ No newline at end of file diff --git a/NzbDrone.Api/Validation/RuleBuilderExtensions.cs b/NzbDrone.Api/Validation/RuleBuilderExtensions.cs index 23dc34c776..b142f5a56c 100644 --- a/NzbDrone.Api/Validation/RuleBuilderExtensions.cs +++ b/NzbDrone.Api/Validation/RuleBuilderExtensions.cs @@ -1,4 +1,6 @@ -using System.Text.RegularExpressions; +using System; +using System.Linq.Expressions; +using System.Text.RegularExpressions; using FluentValidation; using FluentValidation.Validators; @@ -20,5 +22,10 @@ public static IRuleBuilderOptions HaveHttpProtocol(this IRuleBuild { return ruleBuilder.SetValidator(new RegularExpressionValidator("^http(s)?://", RegexOptions.IgnoreCase)).WithMessage("must start with http:// or https://"); } + + public static IRuleBuilderOptions IsValidPath(this IRuleBuilder ruleBuilder) + { + return ruleBuilder.SetValidator(new PathValidator()); + } } } \ No newline at end of file diff --git a/NzbDrone.Common/EnsureThat/EnsureStringExtensions.cs b/NzbDrone.Common/EnsureThat/EnsureStringExtensions.cs index 9a02758940..0cd5954649 100644 --- a/NzbDrone.Common/EnsureThat/EnsureStringExtensions.cs +++ b/NzbDrone.Common/EnsureThat/EnsureStringExtensions.cs @@ -95,8 +95,7 @@ public static Param IsRelativePath(this Param param) return param; } - private static readonly Regex windowsInvalidPathRegex = new Regex(@"[/*<>""|]", RegexOptions.Compiled); - private static readonly Regex windowsPathRegex = new Regex(@"^[a-zA-Z]:\\", RegexOptions.Compiled); + [DebuggerStepThrough] public static Param IsValidPath(this Param param) @@ -104,31 +103,14 @@ public static Param IsValidPath(this Param param) if (string.IsNullOrWhiteSpace(param.Value)) throw ExceptionFactory.CreateForParamValidation(param.Name, ExceptionMessages.EnsureExtensions_IsNotNullOrWhiteSpace); + if (param.Value.IsPathValid()) return param; + if (OsInfo.IsLinux) { - if (!param.Value.StartsWith(Path.DirectorySeparatorChar.ToString())) - { - throw ExceptionFactory.CreateForParamValidation(param.Name, string.Format("value [{0}] is not a valid *nix path. paths must start with /", param.Value)); - } + throw ExceptionFactory.CreateForParamValidation(param.Name, string.Format("value [{0}] is not a valid *nix path. paths must start with /", param.Value)); } - else - { - if (windowsInvalidPathRegex.IsMatch(param.Value)) - { - throw ExceptionFactory.CreateForParamValidation(param.Name, string.Format("value [{0}] is not a valid Windows path. It contains invalid characters", param.Value)); - } - - //Network path - if (param.Value.StartsWith(Path.DirectorySeparatorChar.ToString())) return param; - - if (!windowsPathRegex.IsMatch(param.Value)) - { - throw ExceptionFactory.CreateForParamValidation(param.Name, string.Format("value [{0}] is not a valid Windows path. paths must be a full path eg. C:\\Windows", param.Value)); - } - } - - - return param; + + throw ExceptionFactory.CreateForParamValidation(param.Name, string.Format("value [{0}] is not a valid Windows path. paths must be a full path eg. C:\\Windows", param.Value)); } } } diff --git a/NzbDrone.Common/PathExtensions.cs b/NzbDrone.Common/PathExtensions.cs index 374d2372a4..2cdd5dd446 100644 --- a/NzbDrone.Common/PathExtensions.cs +++ b/NzbDrone.Common/PathExtensions.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Text.RegularExpressions; using NzbDrone.Common.EnsureThat; using NzbDrone.Common.EnvironmentInfo; @@ -45,6 +46,32 @@ public static bool PathEquals(this string firstPath, string secondPath) return String.Equals(firstPath.CleanFilePath(), secondPath.CleanFilePath(), StringComparison.InvariantCultureIgnoreCase); } + private static readonly Regex WindowsInvalidPathRegex = new Regex(@"[/*<>""|]", RegexOptions.Compiled); + private static readonly Regex WindowsPathRegex = new Regex(@"^[a-zA-Z]:\\", RegexOptions.Compiled); + + public static bool IsPathValid(this string path) + { + if (OsInfo.IsLinux && !path.StartsWith(Path.DirectorySeparatorChar.ToString())) + { + return false; + } + if (WindowsInvalidPathRegex.IsMatch(path)) + { + return false; + } + + //Network path + if (path.StartsWith(Path.DirectorySeparatorChar.ToString())) return true; + + if (!WindowsPathRegex.IsMatch(path)) + { + return false; + } + + return true; + } + + public static bool ContainsInvalidPathChars(this string text) { return text.IndexOfAny(Path.GetInvalidPathChars()) >= 0; diff --git a/NzbDrone.Core/Validation/RuleBuilderExtensions.cs b/NzbDrone.Core/Validation/RuleBuilderExtensions.cs index 6401fb4753..da8609e844 100644 --- a/NzbDrone.Core/Validation/RuleBuilderExtensions.cs +++ b/NzbDrone.Core/Validation/RuleBuilderExtensions.cs @@ -23,6 +23,7 @@ public static IRuleBuilderOptions HaveHttpProtocol(this IRuleBuild public static IRuleBuilderOptions ValidRootUrl(this IRuleBuilder ruleBuilder) { + ruleBuilder.SetValidator(new NotEmptyValidator(null)); return ruleBuilder.SetValidator(new RegularExpressionValidator("^http(?:s)?://[a-z0-9-.]+", RegexOptions.IgnoreCase)).WithMessage("must be valid URL that"); } } diff --git a/NzbDrone.Integration.Test/IntegrationTest.cs b/NzbDrone.Integration.Test/IntegrationTest.cs index 3ef126a98d..c0bb4b5fdf 100644 --- a/NzbDrone.Integration.Test/IntegrationTest.cs +++ b/NzbDrone.Integration.Test/IntegrationTest.cs @@ -1,4 +1,5 @@ -using NLog; +using System.Runtime.CompilerServices; +using NLog; using NLog.Config; using NLog.Targets; using NUnit.Framework; @@ -39,7 +40,7 @@ public IntegrationTest() LogManager.Configuration.LoggingRules.Add(new LoggingRule("*", LogLevel.Trace, consoleTarget)); } - [SetUp] + [TestFixtureSetUp] public void SmokeTestSetup() { _runner = new NzbDroneRunner(); @@ -63,7 +64,7 @@ private void InitRestClients() NamingConfig = new ClientBase(RestClient, "config/naming"); } - [TearDown] + [TestFixtureTearDown] public void SmokeTestTearDown() { _runner.KillAll(); diff --git a/NzbDrone.Integration.Test/RootFolderIntegrationTest.cs b/NzbDrone.Integration.Test/RootFolderIntegrationTest.cs index cd1b29cf04..8a888fffa6 100644 --- a/NzbDrone.Integration.Test/RootFolderIntegrationTest.cs +++ b/NzbDrone.Integration.Test/RootFolderIntegrationTest.cs @@ -58,5 +58,17 @@ public void should_have_no_root_folder_initially() RootFolders.All().Should().BeEmpty(); } + + [Test] + public void invalid_path_should_return_bad_request() + { + var rootFolder = new RootFolderResource + { + Path = "invalid_path" + }; + + var postResponse = RootFolders.InvalidPost(rootFolder); + postResponse.Should().NotBeEmpty(); + } } } \ No newline at end of file diff --git a/NzbDrone.Integration.Test/SeriesIntegrationTest.cs b/NzbDrone.Integration.Test/SeriesIntegrationTest.cs index 85ef89050b..c03940490b 100644 --- a/NzbDrone.Integration.Test/SeriesIntegrationTest.cs +++ b/NzbDrone.Integration.Test/SeriesIntegrationTest.cs @@ -9,12 +9,6 @@ namespace NzbDrone.Integration.Test [TestFixture] public class SeriesIntegrationTest : IntegrationTest { - [Test] - public void should_have_no_series_on_start_application() - { - Series.All().Should().BeEmpty(); - } - [Test] public void series_lookup_on_trakt() { diff --git a/UI/AddSeries/RootFolders/Collection.js b/UI/AddSeries/RootFolders/Collection.js index 8f20ac92ab..74b9b45550 100644 --- a/UI/AddSeries/RootFolders/Collection.js +++ b/UI/AddSeries/RootFolders/Collection.js @@ -1,4 +1,4 @@ -'use strict'; +'use strict'; define( [ 'backbone', diff --git a/UI/AddSeries/RootFolders/Layout.js b/UI/AddSeries/RootFolders/Layout.js index 89388b2c24..3a75c0f9ff 100644 --- a/UI/AddSeries/RootFolders/Layout.js +++ b/UI/AddSeries/RootFolders/Layout.js @@ -7,10 +7,11 @@ define( 'AddSeries/RootFolders/Collection', 'AddSeries/RootFolders/Model', 'Shared/LoadingView', + 'Mixins/AsValidatedView', 'Mixins/AutoComplete' - ], function (Marionette, RootFolderCollectionView, RootFolderCollection, RootFolderModel, LoadingView) { + ], function (Marionette, RootFolderCollectionView, RootFolderCollection, RootFolderModel, LoadingView, AsValidatedView) { - return Marionette.Layout.extend({ + var layout = Marionette.Layout.extend({ template: 'AddSeries/RootFolders/LayoutTemplate', ui: { @@ -55,12 +56,16 @@ define( Path: this.ui.pathInput.val() }); - RootFolderCollection.add(newDir); + this.bindToModelValidation(newDir); newDir.save().done(function () { + RootFolderCollection.add(newDir); self.trigger('folderSelected', {model: newDir}); }); } }); + + return AsValidatedView.apply(layout); + }); diff --git a/UI/AddSeries/RootFolders/LayoutTemplate.html b/UI/AddSeries/RootFolders/LayoutTemplate.html index 2a5d5f3505..a62ef128d9 100644 --- a/UI/AddSeries/RootFolders/LayoutTemplate.html +++ b/UI/AddSeries/RootFolders/LayoutTemplate.html @@ -3,10 +3,13 @@

Select Folder