New: Better platform detection specifically for Non-Windows Systems

This commit is contained in:
Keivan Beigi 2017-01-03 18:36:47 -08:00
parent 598b5322b7
commit ad7d571b24
76 changed files with 1125 additions and 473 deletions

View File

@ -14,7 +14,7 @@ namespace NzbDrone.Api.Frontend
{ {
public bool IsCacheable(NancyContext context) public bool IsCacheable(NancyContext context)
{ {
if (!RuntimeInfoBase.IsProduction) if (!RuntimeInfo.IsProduction)
{ {
return false; return false;
} }

View File

@ -74,7 +74,7 @@ namespace NzbDrone.Api.Frontend.Mappers
private string GetIndexText() private string GetIndexText()
{ {
if (RuntimeInfoBase.IsProduction && _generatedContent != null) if (RuntimeInfo.IsProduction && _generatedContent != null)
{ {
return _generatedContent; return _generatedContent;
} }
@ -106,7 +106,7 @@ namespace NzbDrone.Api.Frontend.Mappers
text = text.Replace("APP_BRANCH", _configFileProvider.Branch.ToLower()); text = text.Replace("APP_BRANCH", _configFileProvider.Branch.ToLower());
text = text.Replace("APP_ANALYTICS", _analyticsService.IsEnabled.ToString().ToLowerInvariant()); text = text.Replace("APP_ANALYTICS", _analyticsService.IsEnabled.ToString().ToLowerInvariant());
text = text.Replace("URL_BASE", URL_BASE); text = text.Replace("URL_BASE", URL_BASE);
text = text.Replace("PRODUCTION", RuntimeInfoBase.IsProduction.ToString().ToLowerInvariant()); text = text.Replace("PRODUCTION", RuntimeInfo.IsProduction.ToString().ToLowerInvariant());
_generatedContent = text; _generatedContent = text;

View File

@ -67,7 +67,7 @@ namespace NzbDrone.Api.Frontend.Mappers
private string GetLoginText() private string GetLoginText()
{ {
if (RuntimeInfoBase.IsProduction && _generatedContent != null) if (RuntimeInfo.IsProduction && _generatedContent != null)
{ {
return _generatedContent; return _generatedContent;
} }

View File

@ -21,7 +21,7 @@ namespace NzbDrone.Api.Frontend.Mappers
_diskProvider = diskProvider; _diskProvider = diskProvider;
_logger = logger; _logger = logger;
if (!RuntimeInfoBase.IsProduction) if (!RuntimeInfo.IsProduction)
{ {
_caseSensitive = StringComparison.OrdinalIgnoreCase; _caseSensitive = StringComparison.OrdinalIgnoreCase;
} }

View File

@ -24,9 +24,9 @@ namespace NzbDrone.Api
protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines) protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines)
{ {
Logger.Info("Starting NzbDrone API"); Logger.Info("Starting Web Server");
if (RuntimeInfoBase.IsProduction) if (RuntimeInfo.IsProduction)
{ {
DiagnosticsHook.Disable(pipelines); DiagnosticsHook.Disable(pipelines);
} }

View File

@ -180,7 +180,7 @@ namespace NzbDrone.Api.Series
foreach (var season in resource.Seasons) foreach (var season in resource.Seasons)
{ {
season.Statistics = SeasonStatisticsResourceMapper.ToResource(dictSeasonStats.GetValueOrDefault(season.SeasonNumber)); season.Statistics = dictSeasonStats.GetValueOrDefault(season.SeasonNumber).ToResource();
} }
} }
} }

View File

@ -13,6 +13,8 @@ namespace NzbDrone.Api.System
{ {
private readonly IAppFolderInfo _appFolderInfo; private readonly IAppFolderInfo _appFolderInfo;
private readonly IRuntimeInfo _runtimeInfo; private readonly IRuntimeInfo _runtimeInfo;
private readonly IPlatformInfo _platformInfo;
private readonly IOsInfo _osInfo;
private readonly IRouteCacheProvider _routeCacheProvider; private readonly IRouteCacheProvider _routeCacheProvider;
private readonly IConfigFileProvider _configFileProvider; private readonly IConfigFileProvider _configFileProvider;
private readonly IMainDatabase _database; private readonly IMainDatabase _database;
@ -20,14 +22,17 @@ namespace NzbDrone.Api.System
public SystemModule(IAppFolderInfo appFolderInfo, public SystemModule(IAppFolderInfo appFolderInfo,
IRuntimeInfo runtimeInfo, IRuntimeInfo runtimeInfo,
IPlatformInfo platformInfo,
IOsInfo osInfo,
IRouteCacheProvider routeCacheProvider, IRouteCacheProvider routeCacheProvider,
IConfigFileProvider configFileProvider, IConfigFileProvider configFileProvider,
IMainDatabase database, IMainDatabase database,
ILifecycleService lifecycleService) ILifecycleService lifecycleService) : base("system")
: base("system")
{ {
_appFolderInfo = appFolderInfo; _appFolderInfo = appFolderInfo;
_runtimeInfo = runtimeInfo; _runtimeInfo = runtimeInfo;
_platformInfo = platformInfo;
_osInfo = osInfo;
_routeCacheProvider = routeCacheProvider; _routeCacheProvider = routeCacheProvider;
_configFileProvider = configFileProvider; _configFileProvider = configFileProvider;
_database = database; _database = database;
@ -41,27 +46,29 @@ namespace NzbDrone.Api.System
private Response GetStatus() private Response GetStatus()
{ {
return new return new
{ {
Version = BuildInfo.Version.ToString(), Version = BuildInfo.Version.ToString(),
BuildTime = BuildInfo.BuildDateTime, BuildTime = BuildInfo.BuildDateTime,
IsDebug = BuildInfo.IsDebug, IsDebug = BuildInfo.IsDebug,
IsProduction = RuntimeInfoBase.IsProduction, IsProduction = RuntimeInfo.IsProduction,
IsAdmin = _runtimeInfo.IsAdmin, IsAdmin = _runtimeInfo.IsAdmin,
IsUserInteractive = RuntimeInfoBase.IsUserInteractive, IsUserInteractive = RuntimeInfo.IsUserInteractive,
StartupPath = _appFolderInfo.StartUpFolder, StartupPath = _appFolderInfo.StartUpFolder,
AppData = _appFolderInfo.GetAppDataPath(), AppData = _appFolderInfo.GetAppDataPath(),
OsVersion = OsInfo.Version.ToString(), OsName = _osInfo.Name,
IsMonoRuntime = OsInfo.IsMonoRuntime, OsVersion = _osInfo.Version,
IsMono = OsInfo.IsNotWindows, IsMonoRuntime = PlatformInfo.IsMono,
IsLinux = OsInfo.IsLinux, IsMono = PlatformInfo.IsMono,
IsOsx = OsInfo.IsOsx, IsLinux = OsInfo.IsLinux,
IsWindows = OsInfo.IsWindows, IsOsx = OsInfo.IsOsx,
Branch = _configFileProvider.Branch, IsWindows = OsInfo.IsWindows,
Authentication = _configFileProvider.AuthenticationMethod, Branch = _configFileProvider.Branch,
SqliteVersion = _database.Version, Authentication = _configFileProvider.AuthenticationMethod,
UrlBase = _configFileProvider.UrlBase, SqliteVersion = _database.Version,
RuntimeVersion = _runtimeInfo.RuntimeVersion UrlBase = _configFileProvider.UrlBase,
}.AsResponse(); RuntimeVersion = _platformInfo.Version,
RuntimeName = PlatformInfo.Platform
}.AsResponse();
} }
private Response GetRoutes() private Response GetRoutes()

View File

@ -29,7 +29,7 @@ namespace NzbDrone.Common.Test
[Test] [Test]
public void IsProduction_should_return_false_when_run_within_nunit() public void IsProduction_should_return_false_when_run_within_nunit()
{ {
RuntimeInfoBase.IsProduction.Should().BeFalse("Process name is " + Process.GetCurrentProcess().ProcessName + " Folder is " + Directory.GetCurrentDirectory()); RuntimeInfo.IsProduction.Should().BeFalse("Process name is " + Process.GetCurrentProcess().ProcessName + " Folder is " + Directory.GetCurrentDirectory());
} }
[Test] [Test]

View File

@ -9,6 +9,7 @@ using Moq;
using NLog; using NLog;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Common.Cache; using NzbDrone.Common.Cache;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Common.Http.Dispatchers; using NzbDrone.Common.Http.Dispatchers;
using NzbDrone.Common.Http.Proxy; using NzbDrone.Common.Http.Proxy;
@ -30,6 +31,12 @@ namespace NzbDrone.Common.Test.Http
[SetUp] [SetUp]
public void SetUp() public void SetUp()
{ {
Mocker.GetMock<IPlatformInfo>().Setup(c => c.Version).Returns(new Version("1.0.0"));
Mocker.GetMock<IOsInfo>().Setup(c => c.Name).Returns("TestOS");
Mocker.GetMock<IOsInfo>().Setup(c => c.Version).Returns("9.0.0");
Mocker.SetConstant<IUserAgentBuilder>(Mocker.Resolve<UserAgentBuilder>());
Mocker.SetConstant<ICacheManager>(Mocker.Resolve<CacheManager>()); Mocker.SetConstant<ICacheManager>(Mocker.Resolve<CacheManager>());
Mocker.SetConstant<ICreateManagedWebProxy>(Mocker.Resolve<ManagedWebProxyFactory>()); Mocker.SetConstant<ICreateManagedWebProxy>(Mocker.Resolve<ManagedWebProxyFactory>());
Mocker.SetConstant<IRateLimitService>(Mocker.Resolve<RateLimitService>()); Mocker.SetConstant<IRateLimitService>(Mocker.Resolve<RateLimitService>());
@ -48,7 +55,7 @@ namespace NzbDrone.Common.Test.Http
[Test] [Test]
public void should_execute_simple_get() public void should_execute_simple_get()
{ {
var request = new HttpRequest(string.Format("http://{0}/get", _httpBinHost)); var request = new HttpRequest($"http://{_httpBinHost}/get");
var response = Subject.Execute(request); var response = Subject.Execute(request);
@ -58,7 +65,7 @@ namespace NzbDrone.Common.Test.Http
[Test] [Test]
public void should_execute_https_get() public void should_execute_https_get()
{ {
var request = new HttpRequest(string.Format("https://{0}/get", _httpBinHost)); var request = new HttpRequest($"https://{_httpBinHost}/get");
var response = Subject.Execute(request); var response = Subject.Execute(request);
@ -68,7 +75,7 @@ namespace NzbDrone.Common.Test.Http
[Test] [Test]
public void should_execute_typed_get() public void should_execute_typed_get()
{ {
var request = new HttpRequest(string.Format("http://{0}/get", _httpBinHost)); var request = new HttpRequest($"http://{_httpBinHost}/get");
var response = Subject.Get<HttpBinResource>(request); var response = Subject.Get<HttpBinResource>(request);
@ -80,7 +87,7 @@ namespace NzbDrone.Common.Test.Http
{ {
var message = "{ my: 1 }"; var message = "{ my: 1 }";
var request = new HttpRequest(string.Format("http://{0}/post", _httpBinHost)); var request = new HttpRequest($"http://{_httpBinHost}/post");
request.SetContent(message); request.SetContent(message);
var response = Subject.Post<HttpBinResource>(request); var response = Subject.Post<HttpBinResource>(request);
@ -91,7 +98,7 @@ namespace NzbDrone.Common.Test.Http
[TestCase("gzip")] [TestCase("gzip")]
public void should_execute_get_using_gzip(string compression) public void should_execute_get_using_gzip(string compression)
{ {
var request = new HttpRequest(string.Format("http://{0}/{1}", _httpBinHost, compression)); var request = new HttpRequest($"http://{_httpBinHost}/{compression}");
var response = Subject.Get<HttpBinResource>(request); var response = Subject.Get<HttpBinResource>(request);
@ -107,7 +114,7 @@ namespace NzbDrone.Common.Test.Http
[TestCase(HttpStatusCode.BadGateway)] [TestCase(HttpStatusCode.BadGateway)]
public void should_throw_on_unsuccessful_status_codes(int statusCode) public void should_throw_on_unsuccessful_status_codes(int statusCode)
{ {
var request = new HttpRequest(string.Format("http://{0}/status/{1}", _httpBinHost, statusCode)); var request = new HttpRequest($"http://{_httpBinHost}/status/{statusCode}");
var exception = Assert.Throws<HttpException>(() => Subject.Get<HttpBinResource>(request)); var exception = Assert.Throws<HttpException>(() => Subject.Get<HttpBinResource>(request));
@ -119,7 +126,7 @@ namespace NzbDrone.Common.Test.Http
[Test] [Test]
public void should_not_follow_redirects_when_not_in_production() public void should_not_follow_redirects_when_not_in_production()
{ {
var request = new HttpRequest(string.Format("http://{0}/redirect/1", _httpBinHost)); var request = new HttpRequest($"http://{_httpBinHost}/redirect/1");
Subject.Get(request); Subject.Get(request);
@ -129,7 +136,7 @@ namespace NzbDrone.Common.Test.Http
[Test] [Test]
public void should_follow_redirects() public void should_follow_redirects()
{ {
var request = new HttpRequest(string.Format("http://{0}/redirect/1", _httpBinHost)); var request = new HttpRequest($"http://{_httpBinHost}/redirect/1");
request.AllowAutoRedirect = true; request.AllowAutoRedirect = true;
Subject.Get(request); Subject.Get(request);
@ -140,7 +147,7 @@ namespace NzbDrone.Common.Test.Http
[Test] [Test]
public void should_send_user_agent() public void should_send_user_agent()
{ {
var request = new HttpRequest(string.Format("http://{0}/get", _httpBinHost)); var request = new HttpRequest($"http://{_httpBinHost}/get");
var response = Subject.Get<HttpBinResource>(request); var response = Subject.Get<HttpBinResource>(request);
@ -154,7 +161,7 @@ namespace NzbDrone.Common.Test.Http
[TestCase("Accept", "text/xml, text/rss+xml, application/rss+xml")] [TestCase("Accept", "text/xml, text/rss+xml, application/rss+xml")]
public void should_send_headers(string header, string value) public void should_send_headers(string header, string value)
{ {
var request = new HttpRequest(string.Format("http://{0}/get", _httpBinHost)); var request = new HttpRequest($"http://{_httpBinHost}/get");
request.Headers.Add(header, value); request.Headers.Add(header, value);
var response = Subject.Get<HttpBinResource>(request); var response = Subject.Get<HttpBinResource>(request);
@ -177,7 +184,7 @@ namespace NzbDrone.Common.Test.Http
[Test] [Test]
public void should_send_cookie() public void should_send_cookie()
{ {
var request = new HttpRequest(string.Format("http://{0}/get", _httpBinHost)); var request = new HttpRequest($"http://{_httpBinHost}/get");
request.Cookies["my"] = "cookie"; request.Cookies["my"] = "cookie";
var response = Subject.Get<HttpBinResource>(request); var response = Subject.Get<HttpBinResource>(request);
@ -194,7 +201,7 @@ namespace NzbDrone.Common.Test.Http
var oldRequest = new HttpRequest("http://eu.httpbin.org/get"); var oldRequest = new HttpRequest("http://eu.httpbin.org/get");
oldRequest.Cookies["my"] = "cookie"; oldRequest.Cookies["my"] = "cookie";
var oldClient = new HttpClient(new IHttpRequestInterceptor[0], Mocker.Resolve<ICacheManager>(), Mocker.Resolve<IRateLimitService>(), Mocker.Resolve<IHttpDispatcher>(), Mocker.Resolve<Logger>()); var oldClient = new HttpClient(new IHttpRequestInterceptor[0], Mocker.Resolve<ICacheManager>(), Mocker.Resolve<IRateLimitService>(), Mocker.Resolve<IHttpDispatcher>(), Mocker.GetMock<IUserAgentBuilder>().Object, Mocker.Resolve<Logger>());
oldClient.Should().NotBeSameAs(Subject); oldClient.Should().NotBeSameAs(Subject);
@ -234,12 +241,12 @@ namespace NzbDrone.Common.Test.Http
[Test] [Test]
public void should_not_store_response_cookie() public void should_not_store_response_cookie()
{ {
var requestSet = new HttpRequest(string.Format("http://{0}/cookies/set?my=cookie", _httpBinHost)); var requestSet = new HttpRequest($"http://{_httpBinHost}/cookies/set?my=cookie");
requestSet.AllowAutoRedirect = false; requestSet.AllowAutoRedirect = false;
var responseSet = Subject.Get(requestSet); var responseSet = Subject.Get(requestSet);
var request = new HttpRequest(string.Format("http://{0}/get", _httpBinHost)); var request = new HttpRequest($"http://{_httpBinHost}/get");
var response = Subject.Get<HttpBinResource>(request); var response = Subject.Get<HttpBinResource>(request);
@ -251,13 +258,13 @@ namespace NzbDrone.Common.Test.Http
[Test] [Test]
public void should_store_response_cookie() public void should_store_response_cookie()
{ {
var requestSet = new HttpRequest(string.Format("http://{0}/cookies/set?my=cookie", _httpBinHost)); var requestSet = new HttpRequest($"http://{_httpBinHost}/cookies/set?my=cookie");
requestSet.AllowAutoRedirect = false; requestSet.AllowAutoRedirect = false;
requestSet.StoreResponseCookie = true; requestSet.StoreResponseCookie = true;
var responseSet = Subject.Get(requestSet); var responseSet = Subject.Get(requestSet);
var request = new HttpRequest(string.Format("http://{0}/get", _httpBinHost)); var request = new HttpRequest($"http://{_httpBinHost}/get");
var response = Subject.Get<HttpBinResource>(request); var response = Subject.Get<HttpBinResource>(request);
@ -273,14 +280,14 @@ namespace NzbDrone.Common.Test.Http
[Test] [Test]
public void should_overwrite_response_cookie() public void should_overwrite_response_cookie()
{ {
var requestSet = new HttpRequest(string.Format("http://{0}/cookies/set?my=cookie", _httpBinHost)); var requestSet = new HttpRequest($"http://{_httpBinHost}/cookies/set?my=cookie");
requestSet.AllowAutoRedirect = false; requestSet.AllowAutoRedirect = false;
requestSet.StoreResponseCookie = true; requestSet.StoreResponseCookie = true;
requestSet.Cookies["my"] = "oldcookie"; requestSet.Cookies["my"] = "oldcookie";
var responseSet = Subject.Get(requestSet); var responseSet = Subject.Get(requestSet);
var request = new HttpRequest(string.Format("http://{0}/get", _httpBinHost)); var request = new HttpRequest($"http://{_httpBinHost}/get");
var response = Subject.Get<HttpBinResource>(request); var response = Subject.Get<HttpBinResource>(request);
@ -296,7 +303,7 @@ namespace NzbDrone.Common.Test.Http
[Test] [Test]
public void should_throw_on_http429_too_many_requests() public void should_throw_on_http429_too_many_requests()
{ {
var request = new HttpRequest(string.Format("http://{0}/status/429", _httpBinHost)); var request = new HttpRequest($"http://{_httpBinHost}/status/429");
Assert.Throws<TooManyRequestsException>(() => Subject.Get(request)); Assert.Throws<TooManyRequestsException>(() => Subject.Get(request));
@ -316,7 +323,7 @@ namespace NzbDrone.Common.Test.Http
.Setup(v => v.PostResponse(It.IsAny<HttpResponse>())) .Setup(v => v.PostResponse(It.IsAny<HttpResponse>()))
.Returns<HttpResponse>(r => r); .Returns<HttpResponse>(r => r);
var request = new HttpRequest(string.Format("http://{0}/get", _httpBinHost)); var request = new HttpRequest($"http://{_httpBinHost}/get");
Subject.Get(request); Subject.Get(request);
@ -338,7 +345,7 @@ namespace NzbDrone.Common.Test.Http
{ {
// the date is bad in the below - should be 13-Jul-2026 // the date is bad in the below - should be 13-Jul-2026
string malformedCookie = @"__cfduid=d29e686a9d65800021c66faca0a29b4261436890790; expires=Mon, 13-Jul-26 16:19:50 GMT; path=/; HttpOnly"; string malformedCookie = @"__cfduid=d29e686a9d65800021c66faca0a29b4261436890790; expires=Mon, 13-Jul-26 16:19:50 GMT; path=/; HttpOnly";
var requestSet = new HttpRequestBuilder(string.Format("http://{0}/response-headers", _httpBinHost)) var requestSet = new HttpRequestBuilder($"http://{_httpBinHost}/response-headers")
.AddQueryParam("Set-Cookie", malformedCookie) .AddQueryParam("Set-Cookie", malformedCookie)
.Build(); .Build();
@ -347,7 +354,7 @@ namespace NzbDrone.Common.Test.Http
var responseSet = Subject.Get(requestSet); var responseSet = Subject.Get(requestSet);
var request = new HttpRequest(string.Format("http://{0}/get", _httpBinHost)); var request = new HttpRequest($"http://{_httpBinHost}/get");
var response = Subject.Get<HttpBinResource>(request); var response = Subject.Get<HttpBinResource>(request);
@ -371,7 +378,7 @@ namespace NzbDrone.Common.Test.Http
{ {
try try
{ {
string url = string.Format("http://{0}/response-headers?Set-Cookie={1}", _httpBinHost, Uri.EscapeUriString(malformedCookie)); string url = $"http://{_httpBinHost}/response-headers?Set-Cookie={Uri.EscapeUriString(malformedCookie)}";
var requestSet = new HttpRequest(url); var requestSet = new HttpRequest(url);
requestSet.AllowAutoRedirect = false; requestSet.AllowAutoRedirect = false;
@ -379,7 +386,7 @@ namespace NzbDrone.Common.Test.Http
var responseSet = Subject.Get(requestSet); var responseSet = Subject.Get(requestSet);
var request = new HttpRequest(string.Format("http://{0}/get", _httpBinHost)); var request = new HttpRequest($"http://{_httpBinHost}/get");
var response = Subject.Get<HttpBinResource>(request); var response = Subject.Get<HttpBinResource>(request);

View File

@ -20,8 +20,8 @@ namespace NzbDrone.Common.Cloud
.CreateFactory(); .CreateFactory();
} }
public IHttpRequestBuilderFactory Services { get; private set; } public IHttpRequestBuilderFactory Services { get; }
public IHttpRequestBuilderFactory SkyHookTvdb { get; private set; } public IHttpRequestBuilderFactory SkyHookTvdb { get; }
} }
} }

View File

@ -16,6 +16,19 @@ namespace NzbDrone.Common.Disk
{ {
private static readonly Logger Logger = NzbDroneLogger.GetLogger(typeof(DiskProviderBase)); private static readonly Logger Logger = NzbDroneLogger.GetLogger(typeof(DiskProviderBase));
public static StringComparison PathStringComparison
{
get
{
if (OsInfo.IsWindows)
{
return StringComparison.OrdinalIgnoreCase;
}
return StringComparison.Ordinal;
}
}
public abstract long? GetAvailableSpace(string path); public abstract long? GetAvailableSpace(string path);
public abstract void InheritFolderPermissions(string filename); public abstract void InheritFolderPermissions(string filename);
public abstract void SetPermissions(string path, string mask, string user, string group); public abstract void SetPermissions(string path, string mask, string user, string group);
@ -86,7 +99,7 @@ namespace NzbDrone.Common.Disk
public bool FileExists(string path) public bool FileExists(string path)
{ {
Ensure.That(path, () => path).IsValidPath(); Ensure.That(path, () => path).IsValidPath();
return FileExists(path, OsInfo.PathStringComparison); return FileExists(path, PathStringComparison);
} }
public bool FileExists(string path, StringComparison stringComparison) public bool FileExists(string path, StringComparison stringComparison)

View File

@ -101,12 +101,12 @@ namespace NzbDrone.Common.EnsureThat
if (param.Value.IsPathValid()) return param; if (param.Value.IsPathValid()) return param;
if (OsInfo.IsNotWindows) if (OsInfo.IsWindows)
{ {
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 Windows path. paths must be a full path eg. C:\\Windows", 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)); throw ExceptionFactory.CreateForParamValidation(param.Name, string.Format("value [{0}] is not a valid *nix path. paths must start with /", param.Value));
} }
} }
} }

View File

@ -41,10 +41,10 @@ namespace NzbDrone.Common.EnvironmentInfo
TempFolder = Path.GetTempPath(); TempFolder = Path.GetTempPath();
} }
public string AppDataFolder { get; private set; } public string AppDataFolder { get; }
public string StartUpFolder { get; private set; } public string StartUpFolder { get; }
public string TempFolder { get; private set; } public string TempFolder { get; }
} }
} }

View File

@ -0,0 +1,9 @@
namespace NzbDrone.Common.EnvironmentInfo
{
public interface IOperatingSystemVersionInfo
{
string Version { get; }
string Name { get; }
string FullName { get; }
}
}

View File

@ -0,0 +1,9 @@
namespace NzbDrone.Common.EnvironmentInfo
{
public interface IOsVersionAdapter
{
bool Enabled { get; }
OsVersionModel Read();
}
}

View File

@ -0,0 +1,37 @@
using System;
namespace NzbDrone.Common.EnvironmentInfo
{
public enum PlatformType
{
DotNet = 0,
Mono = 1
}
public interface IPlatformInfo
{
Version Version { get; }
}
public abstract class PlatformInfo : IPlatformInfo
{
static PlatformInfo()
{
if (Type.GetType("Mono.Runtime") != null)
{
Platform = PlatformType.Mono;
}
else
{
Platform = PlatformType.DotNet;
}
}
public static PlatformType Platform { get; }
public static bool IsMono => Platform == PlatformType.Mono;
public static bool IsDotNet => Platform == PlatformType.DotNet;
public abstract Version Version { get; }
}
}

View File

@ -1,14 +1,14 @@
namespace NzbDrone.Common.EnvironmentInfo using System;
namespace NzbDrone.Common.EnvironmentInfo
{ {
public interface IRuntimeInfo public interface IRuntimeInfo
{ {
bool IsUserInteractive { get; } bool IsUserInteractive { get; }
bool IsAdmin { get; } bool IsAdmin { get; }
bool IsWindowsService { get; } bool IsWindowsService { get; }
bool IsConsole { get; } bool IsExiting { get; set; }
bool IsRunning { get; set; }
bool RestartPending { get; set; } bool RestartPending { get; set; }
string ExecutingApplication { get; } string ExecutingApplication { get; }
string RuntimeVersion { get; }
} }
} }

View File

@ -1,87 +1,95 @@
using System; using System;
using System.Diagnostics; using System.Collections.Generic;
using System.Globalization; using System.IO;
using System.Runtime.InteropServices; using System.Linq;
using NLog;
namespace NzbDrone.Common.EnvironmentInfo namespace NzbDrone.Common.EnvironmentInfo
{ {
public static class OsInfo public class OsInfo : IOsInfo
{ {
public static Os Os { get; }
public static bool IsNotWindows => !IsWindows;
public static bool IsLinux => Os == Os.Linux;
public static bool IsOsx => Os == Os.Osx;
public static bool IsWindows => Os == Os.Windows;
public string Version { get; }
public string Name { get; }
public string FullName { get; }
static OsInfo() static OsInfo()
{ {
var platform = (int)Environment.OSVersion.Platform; var platform = Environment.OSVersion.Platform;
Version = Environment.OSVersion.Version; switch (platform)
IsMonoRuntime = Type.GetType("Mono.Runtime") != null;
IsNotWindows = (platform == 4) || (platform == 6) || (platform == 128);
IsOsx = IsRunningOnMac();
IsLinux = IsNotWindows && !IsOsx;
IsWindows = !IsNotWindows;
FirstDayOfWeek = CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek;
if (IsWindows)
{ {
Os = Os.Windows; case PlatformID.Win32NT:
PathStringComparison = StringComparison.OrdinalIgnoreCase; {
Os = Os.Windows;
break;
}
case PlatformID.MacOSX:
case PlatformID.Unix:
{
// Sometimes Mac OS reports itself as Unix
if (Directory.Exists("/System/Library/CoreServices/") &&
(File.Exists("/System/Library/CoreServices/SystemVersion.plist") ||
File.Exists("/System/Library/CoreServices/ServerVersion.plist"))
)
{
Os = Os.Osx;
}
else
{
Os = Os.Linux;
}
break;
}
}
}
public OsInfo(IEnumerable<IOsVersionAdapter> versionAdapters, Logger logger)
{
OsVersionModel osInfo = null;
foreach (var osVersionAdapter in versionAdapters.Where(c => c.Enabled))
{
try
{
osInfo = osVersionAdapter.Read();
}
catch (Exception e)
{
logger.Error(e, "Couldn't get OS Version info");
}
if (osInfo != null)
{
break;
}
}
if (osInfo != null)
{
Name = osInfo.Name;
Version = osInfo.Version;
FullName = osInfo.FullName;
} }
else else
{ {
Os = IsOsx ? Os.Osx : Os.Linux; Name = Os.ToString();
FullName = Name;
PathStringComparison = StringComparison.Ordinal;
} }
} }
}
public static Version Version { get; private set; } public interface IOsInfo
public static bool IsMonoRuntime { get; private set; } {
public static bool IsNotWindows { get; private set; } string Version { get; }
public static bool IsLinux { get; private set; } string Name { get; }
public static bool IsOsx { get; private set; } string FullName { get; }
public static bool IsWindows { get; private set; }
public static Os Os { get; private set; }
public static DayOfWeek FirstDayOfWeek { get; private set; }
public static StringComparison PathStringComparison { get; private set; }
//Borrowed from: https://github.com/jpobst/Pinta/blob/master/Pinta.Core/Managers/SystemManager.cs
//From Managed.Windows.Forms/XplatUI
[DllImport("libc")]
static extern int uname(IntPtr buf);
[DebuggerStepThrough]
static bool IsRunningOnMac()
{
var buf = IntPtr.Zero;
try
{
buf = Marshal.AllocHGlobal(8192);
// This is a hacktastic way of getting sysname from uname ()
if (uname(buf) == 0)
{
var os = Marshal.PtrToStringAnsi(buf);
if (os == "Darwin")
{
return true;
}
}
}
catch
{
}
finally
{
if (buf != IntPtr.Zero)
{
Marshal.FreeHGlobal(buf);
}
}
return false;
}
} }
public enum Os public enum Os

View File

@ -0,0 +1,29 @@
namespace NzbDrone.Common.EnvironmentInfo
{
public class OsVersionModel
{
public OsVersionModel(string name, string version, string fullName = null)
{
Name = Trim(name);
Version = Trim(version);
if (string.IsNullOrWhiteSpace(fullName))
{
fullName = $"{Name} {Version}";
}
FullName = Trim(fullName);
}
private static string Trim(string source)
{
return source.Trim().Trim('"', '\'');
}
public string Name { get; }
public string FullName { get; }
public string Version { get; }
}
}

View File

@ -5,15 +5,14 @@ using System.Reflection;
using System.Security.Principal; using System.Security.Principal;
using System.ServiceProcess; using System.ServiceProcess;
using NLog; using NLog;
using NzbDrone.Common.Processes;
namespace NzbDrone.Common.EnvironmentInfo namespace NzbDrone.Common.EnvironmentInfo
{ {
public abstract class RuntimeInfoBase : IRuntimeInfo public class RuntimeInfo : IRuntimeInfo
{ {
private readonly Logger _logger; private readonly Logger _logger;
public RuntimeInfoBase(IServiceProvider serviceProvider, Logger logger) public RuntimeInfo(IServiceProvider serviceProvider, Logger logger)
{ {
_logger = logger; _logger = logger;
@ -31,7 +30,7 @@ namespace NzbDrone.Common.EnvironmentInfo
} }
} }
static RuntimeInfoBase() static RuntimeInfo()
{ {
IsProduction = InternalIsProduction(); IsProduction = InternalIsProduction();
} }
@ -59,31 +58,18 @@ namespace NzbDrone.Common.EnvironmentInfo
public bool IsWindowsService { get; private set; } public bool IsWindowsService { get; private set; }
public bool IsConsole public bool IsExiting { get; set; }
{
get
{
if (OsInfo.IsWindows)
{
return IsUserInteractive && Process.GetCurrentProcess().ProcessName.Equals(ProcessProvider.NZB_DRONE_CONSOLE_PROCESS_NAME, StringComparison.InvariantCultureIgnoreCase);
}
return true;
}
}
public bool IsRunning { get; set; }
public bool RestartPending { get; set; } public bool RestartPending { get; set; }
public string ExecutingApplication { get; private set; } public string ExecutingApplication { get; }
public abstract string RuntimeVersion { get; } public static bool IsProduction { get; }
public static bool IsProduction { get; private set; }
private static bool InternalIsProduction() private static bool InternalIsProduction()
{ {
if (BuildInfo.IsDebug || Debugger.IsAttached) return false; if (BuildInfo.IsDebug || Debugger.IsAttached) return false;
if (BuildInfo.Version.Revision > 10000) return false; //Official builds will never have such a high revision
//Official builds will never have such a high revision
if (BuildInfo.Version.Revision > 10000) return false;
try try
{ {
@ -99,17 +85,17 @@ namespace NzbDrone.Common.EnvironmentInfo
} }
try try
{ {
var currentAssmeblyLocation = typeof(RuntimeInfoBase).Assembly.Location; var currentAssemblyLocation = typeof(RuntimeInfo).Assembly.Location;
if(currentAssmeblyLocation.ToLower().Contains("_output"))return false; if (currentAssemblyLocation.ToLower().Contains("_output")) return false;
} }
catch catch
{ {
} }
string lowerCurrentDir = Directory.GetCurrentDirectory().ToLower(); var lowerCurrentDir = Directory.GetCurrentDirectory().ToLower();
if (lowerCurrentDir.Contains("teamcity")) return false; if (lowerCurrentDir.Contains("teamcity")) return false;
if (lowerCurrentDir.Contains("_output")) return false; if (lowerCurrentDir.Contains("_output")) return false;

View File

@ -1,31 +0,0 @@
using System;
using NzbDrone.Common.EnvironmentInfo;
namespace NzbDrone.Common.Exceptron
{
public static class ExceptionExtentions
{
private const string IGNORE_FLAG = "exceptron_ignore";
public static Exception ExceptronIgnoreOnMono(this Exception exception)
{
if (OsInfo.IsNotWindows)
{
exception.ExceptronIgnore();
}
return exception;
}
public static Exception ExceptronIgnore(this Exception exception)
{
exception.Data.Add(IGNORE_FLAG, true);
return exception;
}
public static bool ExceptronShouldIgnore(this Exception exception)
{
return exception.Data.Contains(IGNORE_FLAG);
}
}
}

View File

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using NzbDrone.Common.Disk;
using NzbDrone.Common.EnsureThat; using NzbDrone.Common.EnsureThat;
using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.EnvironmentInfo;
@ -47,7 +48,7 @@ namespace NzbDrone.Common.Extensions
{ {
if (!comparison.HasValue) if (!comparison.HasValue)
{ {
comparison = OsInfo.PathStringComparison; comparison = DiskProviderBase.PathStringComparison;
} }
if (firstPath.Equals(secondPath, comparison.Value)) return true; if (firstPath.Equals(secondPath, comparison.Value)) return true;
@ -93,7 +94,7 @@ namespace NzbDrone.Common.Extensions
while (child.Parent != null) while (child.Parent != null)
{ {
if (child.Parent.FullName.Equals(parent.FullName, OsInfo.PathStringComparison)) if (child.Parent.FullName.Equals(parent.FullName, DiskProviderBase.PathStringComparison))
{ {
return true; return true;
} }

View File

@ -21,6 +21,7 @@ namespace NzbDrone.Common.Http.Dispatchers
private static readonly Regex ExpiryDate = new Regex(@"(expires=)([^;]+)", RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Regex ExpiryDate = new Regex(@"(expires=)([^;]+)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
private readonly IHttpProxySettingsProvider _proxySettingsProvider; private readonly IHttpProxySettingsProvider _proxySettingsProvider;
private readonly IUserAgentBuilder _userAgentBuilder;
private readonly Logger _logger; private readonly Logger _logger;
private const string _caBundleFileName = "curl-ca-bundle.crt"; private const string _caBundleFileName = "curl-ca-bundle.crt";
@ -38,9 +39,10 @@ namespace NzbDrone.Common.Http.Dispatchers
} }
} }
public CurlHttpDispatcher(IHttpProxySettingsProvider proxySettingsProvider, Logger logger) public CurlHttpDispatcher(IHttpProxySettingsProvider proxySettingsProvider, IUserAgentBuilder userAgentBuilder, Logger logger)
{ {
_proxySettingsProvider = proxySettingsProvider; _proxySettingsProvider = proxySettingsProvider;
_userAgentBuilder = userAgentBuilder;
_logger = logger; _logger = logger;
} }
@ -102,9 +104,9 @@ namespace NzbDrone.Common.Http.Dispatchers
break; break;
default: default:
throw new NotSupportedException(string.Format("HttpCurl method {0} not supported", request.Method)); throw new NotSupportedException($"HttpCurl method {request.Method} not supported");
} }
curlEasy.UserAgent = request.UseSimplifiedUserAgent ? UserAgentBuilder.UserAgentSimplified : UserAgentBuilder.UserAgent; ; curlEasy.UserAgent = _userAgentBuilder.GetUserAgent(request.UseSimplifiedUserAgent);
curlEasy.FollowLocation = request.AllowAutoRedirect; curlEasy.FollowLocation = request.AllowAutoRedirect;
if (request.RequestTimeout != TimeSpan.Zero) if (request.RequestTimeout != TimeSpan.Zero)

View File

@ -10,21 +10,23 @@ namespace NzbDrone.Common.Http.Dispatchers
{ {
private readonly ManagedHttpDispatcher _managedDispatcher; private readonly ManagedHttpDispatcher _managedDispatcher;
private readonly CurlHttpDispatcher _curlDispatcher; private readonly CurlHttpDispatcher _curlDispatcher;
private readonly IPlatformInfo _platformInfo;
private readonly Logger _logger; private readonly Logger _logger;
private readonly ICached<bool> _curlTLSFallbackCache; private readonly ICached<bool> _curlTLSFallbackCache;
public FallbackHttpDispatcher(ManagedHttpDispatcher managedDispatcher, CurlHttpDispatcher curlDispatcher, ICacheManager cacheManager, Logger logger) public FallbackHttpDispatcher(ManagedHttpDispatcher managedDispatcher, CurlHttpDispatcher curlDispatcher, ICacheManager cacheManager, IPlatformInfo platformInfo, Logger logger)
{ {
_managedDispatcher = managedDispatcher; _managedDispatcher = managedDispatcher;
_curlDispatcher = curlDispatcher; _curlDispatcher = curlDispatcher;
_platformInfo = platformInfo;
_curlTLSFallbackCache = cacheManager.GetCache<bool>(GetType(), "curlTLSFallback"); _curlTLSFallbackCache = cacheManager.GetCache<bool>(GetType(), "curlTLSFallback");
_logger = logger; _logger = logger;
} }
public HttpResponse GetResponse(HttpRequest request, CookieContainer cookies) public HttpResponse GetResponse(HttpRequest request, CookieContainer cookies)
{ {
if (OsInfo.IsMonoRuntime && request.Url.Scheme == "https") if (PlatformInfo.IsMono && request.Url.Scheme == "https")
{ {
if (!_curlTLSFallbackCache.Find(request.Url.Host)) if (!_curlTLSFallbackCache.Find(request.Url.Host))
{ {

View File

@ -11,11 +11,13 @@ namespace NzbDrone.Common.Http.Dispatchers
{ {
private readonly IHttpProxySettingsProvider _proxySettingsProvider; private readonly IHttpProxySettingsProvider _proxySettingsProvider;
private readonly ICreateManagedWebProxy _createManagedWebProxy; private readonly ICreateManagedWebProxy _createManagedWebProxy;
private readonly IUserAgentBuilder _userAgentBuilder;
public ManagedHttpDispatcher(IHttpProxySettingsProvider proxySettingsProvider, ICreateManagedWebProxy createManagedWebProxy) public ManagedHttpDispatcher(IHttpProxySettingsProvider proxySettingsProvider, ICreateManagedWebProxy createManagedWebProxy, IUserAgentBuilder userAgentBuilder)
{ {
_proxySettingsProvider = proxySettingsProvider; _proxySettingsProvider = proxySettingsProvider;
_createManagedWebProxy = createManagedWebProxy; _createManagedWebProxy = createManagedWebProxy;
_userAgentBuilder = userAgentBuilder;
} }
public HttpResponse GetResponse(HttpRequest request, CookieContainer cookies) public HttpResponse GetResponse(HttpRequest request, CookieContainer cookies)
@ -28,7 +30,7 @@ namespace NzbDrone.Common.Http.Dispatchers
webRequest.AutomaticDecompression = DecompressionMethods.GZip; webRequest.AutomaticDecompression = DecompressionMethods.GZip;
webRequest.Method = request.Method.ToString(); webRequest.Method = request.Method.ToString();
webRequest.UserAgent = request.UseSimplifiedUserAgent ? UserAgentBuilder.UserAgentSimplified : UserAgentBuilder.UserAgent; webRequest.UserAgent = _userAgentBuilder.GetUserAgent(request.UseSimplifiedUserAgent);
webRequest.KeepAlive = request.ConnectionKeepAlive; webRequest.KeepAlive = request.ConnectionKeepAlive;
webRequest.AllowAutoRedirect = request.AllowAutoRedirect; webRequest.AllowAutoRedirect = request.AllowAutoRedirect;
webRequest.CookieContainer = cookies; webRequest.CookieContainer = cookies;

View File

@ -30,12 +30,19 @@ namespace NzbDrone.Common.Http
private readonly ICached<CookieContainer> _cookieContainerCache; private readonly ICached<CookieContainer> _cookieContainerCache;
private readonly List<IHttpRequestInterceptor> _requestInterceptors; private readonly List<IHttpRequestInterceptor> _requestInterceptors;
private readonly IHttpDispatcher _httpDispatcher; private readonly IHttpDispatcher _httpDispatcher;
private readonly IUserAgentBuilder _userAgentBuilder;
public HttpClient(IEnumerable<IHttpRequestInterceptor> requestInterceptors, ICacheManager cacheManager, IRateLimitService rateLimitService, IHttpDispatcher httpDispatcher, Logger logger) public HttpClient(IEnumerable<IHttpRequestInterceptor> requestInterceptors,
ICacheManager cacheManager,
IRateLimitService rateLimitService,
IHttpDispatcher httpDispatcher,
IUserAgentBuilder userAgentBuilder,
Logger logger)
{ {
_requestInterceptors = requestInterceptors.ToList(); _requestInterceptors = requestInterceptors.ToList();
_rateLimitService = rateLimitService; _rateLimitService = rateLimitService;
_httpDispatcher = httpDispatcher; _httpDispatcher = httpDispatcher;
_userAgentBuilder = userAgentBuilder;
_logger = logger; _logger = logger;
ServicePointManager.DefaultConnectionLimit = 12; ServicePointManager.DefaultConnectionLimit = 12;
@ -78,7 +85,7 @@ namespace NzbDrone.Common.Http
_logger.Trace("Response content ({0} bytes): {1}", response.ResponseData.Length, response.Content); _logger.Trace("Response content ({0} bytes): {1}", response.ResponseData.Length, response.Content);
} }
if (!RuntimeInfoBase.IsProduction && if (!RuntimeInfo.IsProduction &&
(response.StatusCode == HttpStatusCode.Moved || (response.StatusCode == HttpStatusCode.Moved ||
response.StatusCode == HttpStatusCode.MovedPermanently || response.StatusCode == HttpStatusCode.MovedPermanently ||
response.StatusCode == HttpStatusCode.Found)) response.StatusCode == HttpStatusCode.Found))
@ -163,7 +170,7 @@ namespace NzbDrone.Common.Http
var stopWatch = Stopwatch.StartNew(); var stopWatch = Stopwatch.StartNew();
var webClient = new GZipWebClient(); var webClient = new GZipWebClient();
webClient.Headers.Add(HttpRequestHeader.UserAgent, UserAgentBuilder.UserAgent); webClient.Headers.Add(HttpRequestHeader.UserAgent, _userAgentBuilder.GetUserAgent());
webClient.DownloadFile(url, fileName); webClient.DownloadFile(url, fileName);
stopWatch.Stop(); stopWatch.Stop();
_logger.Debug("Downloading Completed. took {0:0}s", stopWatch.Elapsed.Seconds); _logger.Debug("Downloading Completed. took {0:0}s", stopWatch.Elapsed.Seconds);

View File

@ -15,7 +15,7 @@ namespace NzbDrone.Common.Http
AllowAutoRedirect = true; AllowAutoRedirect = true;
Cookies = new Dictionary<string, string>(); Cookies = new Dictionary<string, string>();
if (!RuntimeInfoBase.IsProduction) if (!RuntimeInfo.IsProduction)
{ {
AllowAutoRedirect = false; AllowAutoRedirect = false;
} }

View File

@ -2,19 +2,33 @@ using NzbDrone.Common.EnvironmentInfo;
namespace NzbDrone.Common.Http namespace NzbDrone.Common.Http
{ {
public static class UserAgentBuilder public interface IUserAgentBuilder
{ {
public static string UserAgent { get; private set; } string GetUserAgent(bool simplified = false);
public static string UserAgentSimplified { get; private set; } }
static UserAgentBuilder() public class UserAgentBuilder : IUserAgentBuilder
{
private readonly string _userAgentSimplified;
private readonly string _userAgent;
public string GetUserAgent(bool simplified)
{ {
UserAgent = string.Format("Sonarr/{0} ({1} {2})", if (simplified)
BuildInfo.Version, {
OsInfo.Os, OsInfo.Version.ToString(2)); return _userAgentSimplified;
}
UserAgentSimplified = string.Format("Sonarr/{0}", return _userAgent;
BuildInfo.Version.ToString(2)); }
public UserAgentBuilder(IOsInfo osInfo)
{
var osName = osInfo.Name.ToLower();
var osVersion = osInfo.Version.ToLower();
_userAgent = $"Sonarr/{BuildInfo.Version} ({osName} {osVersion})";
_userAgentSimplified = $"Sonarr/{BuildInfo.Version.ToString(2)}";
} }
} }
} }

View File

@ -1,89 +0,0 @@
using System;
using NLog;
using NLog.Common;
using NLog.Layouts;
using NLog.Targets;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Exceptron;
using NzbDrone.Common.Exceptron.Configuration;
namespace NzbDrone.Common.Instrumentation
{
/// <summary>
/// <see cref="NLog"/> target for exceptron. Allows you to automatically report all
/// exceptions logged to Nlog/>
/// </summary>
[Target("Exceptron")]
public class ExceptronTarget : Target
{
/// <summary>
/// <see cref="ExceptronClient"/> instance that Nlog Target uses to report the exceptions.
/// </summary>
public IExceptronClient ExceptronClient { get; internal set; }
protected override void InitializeTarget()
{
var config = new ExceptronConfiguration
{
ApiKey = "d64e0a72845d495abc625af3a27cf5f5",
IncludeMachineName = true,
};
if (RuntimeInfoBase.IsProduction)
{
config.ApiKey = "82c0f66dd2d64d1480cc88b551c9bdd8";
}
ExceptronClient = new ExceptronClient(config, BuildInfo.Version);
}
/// <summary>
/// String that identifies the active user
/// </summary>
public Layout UserId { get; set; }
protected override void Write(LogEventInfo logEvent)
{
if (logEvent == null || logEvent.Exception == null || logEvent.Exception.ExceptronShouldIgnore()) return;
try
{
var exceptionData = new ExceptionData
{
Exception = logEvent.Exception,
Component = logEvent.LoggerName,
Message = logEvent.FormattedMessage,
};
if (UserId != null)
{
exceptionData.UserId = UserId.Render(logEvent);
}
if (logEvent.Level <= LogLevel.Info)
{
exceptionData.Severity = ExceptionSeverity.None;
}
else if (logEvent.Level <= LogLevel.Warn)
{
exceptionData.Severity = ExceptionSeverity.Warning;
}
else if (logEvent.Level <= LogLevel.Error)
{
exceptionData.Severity = ExceptionSeverity.Error;
}
else if (logEvent.Level <= LogLevel.Fatal)
{
exceptionData.Severity = ExceptionSeverity.Fatal;
}
ExceptronClient.SubmitException(exceptionData);
}
catch (Exception e)
{
InternalLogger.Warn("Unable to report exception. {0}", e);
}
}
}
}

View File

@ -35,7 +35,7 @@ namespace NzbDrone.Common.Instrumentation
return; return;
} }
if (OsInfo.IsMonoRuntime) if (PlatformInfo.IsMono)
{ {
if (exception is TypeInitializationException && exception.InnerException is DllNotFoundException || if (exception is TypeInitializationException && exception.InnerException is DllNotFoundException ||
exception is DllNotFoundException) exception is DllNotFoundException)

View File

@ -48,7 +48,7 @@ namespace NzbDrone.Common.Instrumentation
} }
else else
{ {
if (inConsole && (OsInfo.IsNotWindows || RuntimeInfoBase.IsUserInteractive)) if (inConsole && (OsInfo.IsNotWindows || RuntimeInfo.IsUserInteractive))
{ {
RegisterConsole(); RegisterConsole();
} }
@ -152,16 +152,6 @@ namespace NzbDrone.Common.Instrumentation
LogManager.Configuration.LoggingRules.Add(loggingRule); LogManager.Configuration.LoggingRules.Add(loggingRule);
} }
private static void RegisterExceptron()
{
var exceptronTarget = new ExceptronTarget();
var rule = new LoggingRule("*", LogLevel.Warn, exceptronTarget);
LogManager.Configuration.AddTarget("ExceptronTarget", exceptronTarget);
LogManager.Configuration.LoggingRules.Add(rule);
}
public static Logger GetLogger(Type obj) public static Logger GetLogger(Type obj)
{ {
return LogManager.GetLogger(obj.Name.Replace("NzbDrone.", "")); return LogManager.GetLogger(obj.Name.Replace("NzbDrone.", ""));

View File

@ -88,6 +88,9 @@
<Compile Include="Disk\RelativeFileSystemModel.cs" /> <Compile Include="Disk\RelativeFileSystemModel.cs" />
<Compile Include="Disk\FileSystemModel.cs" /> <Compile Include="Disk\FileSystemModel.cs" />
<Compile Include="Disk\FileSystemResult.cs" /> <Compile Include="Disk\FileSystemResult.cs" />
<Compile Include="EnvironmentInfo\IOsVersionAdapter.cs" />
<Compile Include="EnvironmentInfo\IPlatformInfo.cs" />
<Compile Include="EnvironmentInfo\OsVersionModel.cs" />
<Compile Include="Extensions\DictionaryExtensions.cs" /> <Compile Include="Extensions\DictionaryExtensions.cs" />
<Compile Include="Disk\OsPath.cs" /> <Compile Include="Disk\OsPath.cs" />
<Compile Include="Disk\DiskProviderBase.cs" /> <Compile Include="Disk\DiskProviderBase.cs" />
@ -118,13 +121,12 @@
<Compile Include="EnvironmentInfo\BuildInfo.cs" /> <Compile Include="EnvironmentInfo\BuildInfo.cs" />
<Compile Include="EnvironmentInfo\OsInfo.cs" /> <Compile Include="EnvironmentInfo\OsInfo.cs" />
<Compile Include="EnvironmentInfo\IRuntimeInfo.cs" /> <Compile Include="EnvironmentInfo\IRuntimeInfo.cs" />
<Compile Include="EnvironmentInfo\RuntimeInfoBase.cs" /> <Compile Include="EnvironmentInfo\RuntimeInfo.cs" />
<Compile Include="EnvironmentInfo\StartupContext.cs" /> <Compile Include="EnvironmentInfo\StartupContext.cs" />
<Compile Include="Exceptions\NotParentException.cs" /> <Compile Include="Exceptions\NotParentException.cs" />
<Compile Include="Exceptions\NzbDroneException.cs" /> <Compile Include="Exceptions\NzbDroneException.cs" />
<Compile Include="Exceptron\Configuration\ExceptronConfiguration.cs" /> <Compile Include="Exceptron\Configuration\ExceptronConfiguration.cs" />
<Compile Include="Exceptron\ExceptionData.cs" /> <Compile Include="Exceptron\ExceptionData.cs" />
<Compile Include="Exceptron\ExceptionExtentions.cs" />
<Compile Include="Exceptron\ExceptionSeverity.cs" /> <Compile Include="Exceptron\ExceptionSeverity.cs" />
<Compile Include="Exceptron\ExceptronApiException.cs" /> <Compile Include="Exceptron\ExceptronApiException.cs" />
<Compile Include="Exceptron\ExceptronClient.cs" /> <Compile Include="Exceptron\ExceptronClient.cs" />
@ -187,7 +189,6 @@
<Compile Include="Extensions\IEnumerableExtensions.cs" /> <Compile Include="Extensions\IEnumerableExtensions.cs" />
<Compile Include="Http\UserAgentBuilder.cs" /> <Compile Include="Http\UserAgentBuilder.cs" />
<Compile Include="Instrumentation\CleanseLogMessage.cs" /> <Compile Include="Instrumentation\CleanseLogMessage.cs" />
<Compile Include="Instrumentation\ExceptronTarget.cs" />
<Compile Include="Instrumentation\Extensions\LoggerProgressExtensions.cs" /> <Compile Include="Instrumentation\Extensions\LoggerProgressExtensions.cs" />
<Compile Include="Instrumentation\GlobalExceptionHandlers.cs" /> <Compile Include="Instrumentation\GlobalExceptionHandlers.cs" />
<Compile Include="Instrumentation\LogEventExtensions.cs" /> <Compile Include="Instrumentation\LogEventExtensions.cs" />

View File

@ -108,7 +108,7 @@ namespace NzbDrone.Common.Processes
public Process Start(string path, string args = null, StringDictionary environmentVariables = null, Action<string> onOutputDataReceived = null, Action<string> onErrorDataReceived = null) public Process Start(string path, string args = null, StringDictionary environmentVariables = null, Action<string> onOutputDataReceived = null, Action<string> onErrorDataReceived = null)
{ {
if (OsInfo.IsMonoRuntime && path.EndsWith(".exe", StringComparison.InvariantCultureIgnoreCase)) if (PlatformInfo.IsMono && path.EndsWith(".exe", StringComparison.InvariantCultureIgnoreCase))
{ {
args = GetMonoArgs(path, args); args = GetMonoArgs(path, args);
path = "mono"; path = "mono";
@ -174,7 +174,7 @@ namespace NzbDrone.Common.Processes
public Process SpawnNewProcess(string path, string args = null, StringDictionary environmentVariables = null) public Process SpawnNewProcess(string path, string args = null, StringDictionary environmentVariables = null)
{ {
if (OsInfo.IsMonoRuntime && path.EndsWith(".exe", StringComparison.InvariantCultureIgnoreCase)) if (PlatformInfo.IsMono && path.EndsWith(".exe", StringComparison.InvariantCultureIgnoreCase))
{ {
args = GetMonoArgs(path, args); args = GetMonoArgs(path, args);
path = "mono"; path = "mono";

View File

@ -1,6 +1,8 @@
using NUnit.Framework; using System;
using NUnit.Framework;
using NzbDrone.Common.Cache; using NzbDrone.Common.Cache;
using NzbDrone.Common.Cloud; using NzbDrone.Common.Cloud;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Http; using NzbDrone.Common.Http;
using NzbDrone.Common.Http.Dispatchers; using NzbDrone.Common.Http.Dispatchers;
using NzbDrone.Common.TPL; using NzbDrone.Common.TPL;
@ -15,12 +17,16 @@ namespace NzbDrone.Core.Test.Framework
{ {
protected void UseRealHttp() protected void UseRealHttp()
{ {
Mocker.GetMock<IPlatformInfo>().SetupGet(c => c.Version).Returns(new Version("3.0.0"));
Mocker.GetMock<IOsInfo>().SetupGet(c=>c.Version).Returns("1.0.0");
Mocker.GetMock<IOsInfo>().SetupGet(c=>c.Name).Returns("TestOS");
Mocker.SetConstant<IHttpProxySettingsProvider>(new HttpProxySettingsProvider(Mocker.Resolve<ConfigService>())); Mocker.SetConstant<IHttpProxySettingsProvider>(new HttpProxySettingsProvider(Mocker.Resolve<ConfigService>()));
Mocker.SetConstant<ICreateManagedWebProxy>(new ManagedWebProxyFactory(Mocker.Resolve<CacheManager>())); Mocker.SetConstant<ICreateManagedWebProxy>(new ManagedWebProxyFactory(Mocker.Resolve<CacheManager>()));
Mocker.SetConstant<ManagedHttpDispatcher>(new ManagedHttpDispatcher(Mocker.Resolve<IHttpProxySettingsProvider>(), Mocker.Resolve<ICreateManagedWebProxy>())); Mocker.SetConstant<ManagedHttpDispatcher>(new ManagedHttpDispatcher(Mocker.Resolve<IHttpProxySettingsProvider>(), Mocker.Resolve<ICreateManagedWebProxy>(), Mocker.Resolve<UserAgentBuilder>()));
Mocker.SetConstant<CurlHttpDispatcher>(new CurlHttpDispatcher(Mocker.Resolve<IHttpProxySettingsProvider>(), Mocker.Resolve<NLog.Logger>())); Mocker.SetConstant<CurlHttpDispatcher>(new CurlHttpDispatcher(Mocker.Resolve<IHttpProxySettingsProvider>(), Mocker.Resolve<UserAgentBuilder>(), Mocker.Resolve<NLog.Logger>()));
Mocker.SetConstant<IHttpProvider>(new HttpProvider(TestLogger)); Mocker.SetConstant<IHttpProvider>(new HttpProvider(TestLogger));
Mocker.SetConstant<IHttpClient>(new HttpClient(new IHttpRequestInterceptor[0], Mocker.Resolve<CacheManager>(), Mocker.Resolve<RateLimitService>(), Mocker.Resolve<FallbackHttpDispatcher>(), TestLogger)); Mocker.SetConstant<IHttpClient>(new HttpClient(new IHttpRequestInterceptor[0], Mocker.Resolve<CacheManager>(), Mocker.Resolve<RateLimitService>(), Mocker.Resolve<FallbackHttpDispatcher>(), Mocker.Resolve<UserAgentBuilder>(), TestLogger));
Mocker.SetConstant<ISonarrCloudRequestBuilder>(new SonarrCloudRequestBuilder()); Mocker.SetConstant<ISonarrCloudRequestBuilder>(new SonarrCloudRequestBuilder());
} }
} }

View File

@ -1,4 +1,5 @@
using NUnit.Framework; using System;
using NUnit.Framework;
using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Core.HealthCheck.Checks; using NzbDrone.Core.HealthCheck.Checks;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
@ -8,17 +9,13 @@ namespace NzbDrone.Core.Test.HealthCheck.Checks
[TestFixture] [TestFixture]
public class MonoVersionCheckFixture : CoreTest<MonoVersionCheck> public class MonoVersionCheckFixture : CoreTest<MonoVersionCheck>
{ {
[SetUp]
public void Setup()
{
MonoOnly();
}
private void GivenOutput(string version) private void GivenOutput(string version)
{ {
Mocker.GetMock<IRuntimeInfo>() MonoOnly();
.SetupGet(s => s.RuntimeVersion)
.Returns(string.Format("{0} (tarball Wed Sep 25 16:35:44 CDT 2013)", version)); Mocker.GetMock<IPlatformInfo>()
.SetupGet(s => s.Version)
.Returns(new Version(version));
} }
[TestCase("3.10")] [TestCase("3.10")]

View File

@ -2,6 +2,7 @@ using System;
using System.Linq; using System.Linq;
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Extensions; using NzbDrone.Common.Extensions;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Update; using NzbDrone.Core.Update;
@ -10,6 +11,12 @@ namespace NzbDrone.Core.Test.UpdateTests
{ {
public class UpdatePackageProviderFixture : CoreTest<UpdatePackageProvider> public class UpdatePackageProviderFixture : CoreTest<UpdatePackageProvider>
{ {
[SetUp]
public void Setup()
{
Mocker.GetMock<IPlatformInfo>().SetupGet(c => c.Version).Returns(new Version("9.9.9"));
}
[Test] [Test]
public void no_update_when_version_higher() public void no_update_when_version_higher()
{ {

View File

@ -17,6 +17,6 @@ namespace NzbDrone.Core.Analytics
_configFileProvider = configFileProvider; _configFileProvider = configFileProvider;
} }
public bool IsEnabled => _configFileProvider.AnalyticsEnabled && RuntimeInfoBase.IsProduction; public bool IsEnabled => _configFileProvider.AnalyticsEnabled && RuntimeInfo.IsProduction;
} }
} }

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization;
using System.Linq; using System.Linq;
using NLog; using NLog;
using NzbDrone.Common.EnsureThat; using NzbDrone.Common.EnsureThat;
@ -246,7 +247,7 @@ namespace NzbDrone.Core.Configuration
public int FirstDayOfWeek public int FirstDayOfWeek
{ {
get { return GetValueInt("FirstDayOfWeek", (int)OsInfo.FirstDayOfWeek); } get { return GetValueInt("FirstDayOfWeek", (int)CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek); }
set { SetValue("FirstDayOfWeek", value); } set { SetValue("FirstDayOfWeek", value); }
} }

View File

@ -1,7 +1,6 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text.RegularExpressions;
using NLog; using NLog;
using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.EnvironmentInfo;
@ -9,50 +8,43 @@ namespace NzbDrone.Core.HealthCheck.Checks
{ {
public class MonoVersionCheck : HealthCheckBase public class MonoVersionCheck : HealthCheckBase
{ {
private readonly IRuntimeInfo _runtimeInfo; private readonly IPlatformInfo _platformInfo;
private readonly Logger _logger; private readonly Logger _logger;
private static readonly Regex VersionRegex = new Regex(@"(?<=\W|^)(?<version>\d+\.\d+(\.\d+)?(\.\d+)?)(?=\W)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
public MonoVersionCheck(IRuntimeInfo runtimeInfo, Logger logger) public MonoVersionCheck(IPlatformInfo platformInfo, Logger logger)
{ {
_runtimeInfo = runtimeInfo; _platformInfo = platformInfo;
_logger = logger; _logger = logger;
} }
public override HealthCheck Check() public override HealthCheck Check()
{ {
if (OsInfo.IsWindows) if (!PlatformInfo.IsMono)
{ {
return new HealthCheck(GetType()); return new HealthCheck(GetType());
} }
var versionString = _runtimeInfo.RuntimeVersion; var monoVersion = _platformInfo.Version;
var versionMatch = VersionRegex.Match(versionString);
if (versionMatch.Success) if (monoVersion == new Version("3.4.0") && HasMonoBug18599())
{ {
var version = new Version(versionMatch.Groups["version"].Value); _logger.Debug("Mono version 3.4.0, checking for Mono bug #18599 returned positive.");
return new HealthCheck(GetType(), HealthCheckResult.Error, "You are running an old and unsupported version of Mono with a known bug. You should upgrade to a higher version");
if (version == new Version(3, 4, 0) && HasMonoBug18599())
{
_logger.Debug("mono version 3.4.0, checking for mono bug #18599 returned positive.");
return new HealthCheck(GetType(), HealthCheckResult.Error, "your mono version 3.4.0 has a critical bug, you should upgrade to a higher version");
}
if (version == new Version(4, 4, 0) || version == new Version(4, 4, 1))
{
_logger.Debug("mono version {0}", version);
return new HealthCheck(GetType(), HealthCheckResult.Error, $"your mono version {version} has a bug that causes issues connecting to indexers/download clients");
}
if (version >= new Version(3, 10))
{
_logger.Debug("mono version is 3.10 or better: {0}", version.ToString());
return new HealthCheck(GetType());
}
} }
return new HealthCheck(GetType(), HealthCheckResult.Warning, "mono version is less than 3.10, upgrade for improved stability"); if (monoVersion == new Version("4.4.0") || monoVersion == new Version("4.4.1"))
{
_logger.Debug("Mono version {0}", monoVersion);
return new HealthCheck(GetType(), HealthCheckResult.Error, $"Your Mono version {monoVersion} has a bug that causes issues connecting to indexers/download clients. You should upgrade to a higher version");
}
if (monoVersion >= new Version("3.10"))
{
_logger.Debug("Mono version is 3.10 or better: {0}", monoVersion);
return new HealthCheck(GetType());
}
return new HealthCheck(GetType(), HealthCheckResult.Warning, "You are running an old and unsupported version of Mono. Please upgrade Mono for improved stability.");
} }
public override bool CheckOnConfigChange => false; public override bool CheckOnConfigChange => false;
@ -70,7 +62,8 @@ namespace NzbDrone.Core.HealthCheck.Checks
return false; return false;
} }
var fieldInfo = numberFormatterType.GetField("userFormatProvider", BindingFlags.Static | BindingFlags.NonPublic); var fieldInfo = numberFormatterType.GetField("userFormatProvider",
BindingFlags.Static | BindingFlags.NonPublic);
if (fieldInfo == null) if (fieldInfo == null)
{ {
@ -87,4 +80,4 @@ namespace NzbDrone.Core.HealthCheck.Checks
return false; return false;
} }
} }
} }

View File

@ -4,13 +4,9 @@ namespace NzbDrone.Core.Lifecycle
{ {
public class ApplicationShutdownRequested : IEvent public class ApplicationShutdownRequested : IEvent
{ {
public bool Restarting { get; set; } public bool Restarting { get; }
public ApplicationShutdownRequested() public ApplicationShutdownRequested(bool restarting = false)
{
}
public ApplicationShutdownRequested(bool restarting)
{ {
Restarting = restarting; Restarting = restarting;
} }

View File

@ -164,7 +164,6 @@ namespace NzbDrone.Core.MediaFiles
catch (Exception ex) catch (Exception ex)
{ {
ex.ExceptronIgnoreOnMono();
_logger.Warn(ex, "Unable to set date of file [" + filePath + "]"); _logger.Warn(ex, "Unable to set date of file [" + filePath + "]");
} }
} }

View File

@ -7,12 +7,11 @@ namespace NzbDrone.Core.Rest
{ {
public static RestClient BuildClient(string baseUrl) public static RestClient BuildClient(string baseUrl)
{ {
var restClient = new RestClient(baseUrl); var restClient = new RestClient(baseUrl)
{
UserAgent = $"Sonarr/{BuildInfo.Version} ({OsInfo.Os})"
};
restClient.UserAgent = string.Format("Sonarr/{0} (RestSharp/{1}; {2}/{3})",
BuildInfo.Version,
restClient.GetType().Assembly.GetName().Version,
OsInfo.Os, OsInfo.Version.ToString(2));
return restClient; return restClient;
} }

View File

@ -1,5 +1,4 @@
using NLog; using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
namespace NzbDrone.Core.Update namespace NzbDrone.Core.Update
@ -14,16 +13,12 @@ namespace NzbDrone.Core.Update
private readonly IUpdatePackageProvider _updatePackageProvider; private readonly IUpdatePackageProvider _updatePackageProvider;
private readonly IConfigFileProvider _configFileProvider; private readonly IConfigFileProvider _configFileProvider;
private readonly Logger _logger;
public CheckUpdateService(IUpdatePackageProvider updatePackageProvider, public CheckUpdateService(IUpdatePackageProvider updatePackageProvider,
IConfigFileProvider configFileProvider, IConfigFileProvider configFileProvider)
Logger logger)
{ {
_updatePackageProvider = updatePackageProvider; _updatePackageProvider = updatePackageProvider;
_configFileProvider = configFileProvider; _configFileProvider = configFileProvider;
_logger = logger;
} }
public UpdatePackage AvailableUpdate() public UpdatePackage AvailableUpdate()

View File

@ -15,11 +15,13 @@ namespace NzbDrone.Core.Update
public class UpdatePackageProvider : IUpdatePackageProvider public class UpdatePackageProvider : IUpdatePackageProvider
{ {
private readonly IHttpClient _httpClient; private readonly IHttpClient _httpClient;
private readonly IPlatformInfo _platformInfo;
private readonly IHttpRequestBuilderFactory _requestBuilder; private readonly IHttpRequestBuilderFactory _requestBuilder;
public UpdatePackageProvider(IHttpClient httpClient, ISonarrCloudRequestBuilder requestBuilder) public UpdatePackageProvider(IHttpClient httpClient, ISonarrCloudRequestBuilder requestBuilder, IPlatformInfo platformInfo)
{ {
_httpClient = httpClient; _httpClient = httpClient;
_platformInfo = platformInfo;
_requestBuilder = requestBuilder.Services; _requestBuilder = requestBuilder.Services;
} }
@ -29,6 +31,7 @@ namespace NzbDrone.Core.Update
.Resource("/update/{branch}") .Resource("/update/{branch}")
.AddQueryParam("version", currentVersion) .AddQueryParam("version", currentVersion)
.AddQueryParam("os", OsInfo.Os.ToString().ToLowerInvariant()) .AddQueryParam("os", OsInfo.Os.ToString().ToLowerInvariant())
.AddQueryParam("runtimeVer", _platformInfo.Version)
.SetSegment("branch", branch) .SetSegment("branch", branch)
.Build(); .Build();
@ -45,6 +48,7 @@ namespace NzbDrone.Core.Update
.Resource("/update/{branch}/changes") .Resource("/update/{branch}/changes")
.AddQueryParam("version", currentVersion) .AddQueryParam("version", currentVersion)
.AddQueryParam("os", OsInfo.Os.ToString().ToLowerInvariant()) .AddQueryParam("os", OsInfo.Os.ToString().ToLowerInvariant())
.AddQueryParam("runtimeVer", _platformInfo.Version)
.SetSegment("branch", branch) .SetSegment("branch", branch)
.Build(); .Build();

View File

@ -20,6 +20,7 @@ namespace NzbDrone.Host.AccessControl
private readonly INetshProvider _netshProvider; private readonly INetshProvider _netshProvider;
private readonly IConfigFileProvider _configFileProvider; private readonly IConfigFileProvider _configFileProvider;
private readonly IRuntimeInfo _runtimeInfo; private readonly IRuntimeInfo _runtimeInfo;
private readonly IOsInfo _osInfo;
private readonly Logger _logger; private readonly Logger _logger;
public List<string> Urls public List<string> Urls
@ -30,19 +31,21 @@ namespace NzbDrone.Host.AccessControl
} }
} }
private List<UrlAcl> InternalUrls { get; set; } private List<UrlAcl> InternalUrls { get; }
private List<UrlAcl> RegisteredUrls { get; set; } private List<UrlAcl> RegisteredUrls { get; }
private static readonly Regex UrlAclRegex = new Regex(@"(?<scheme>https?)\:\/\/(?<address>.+?)\:(?<port>\d+)/(?<urlbase>.+)?", RegexOptions.Compiled | RegexOptions.IgnoreCase); private static readonly Regex UrlAclRegex = new Regex(@"(?<scheme>https?)\:\/\/(?<address>.+?)\:(?<port>\d+)/(?<urlbase>.+)?", RegexOptions.Compiled | RegexOptions.IgnoreCase);
public UrlAclAdapter(INetshProvider netshProvider, public UrlAclAdapter(INetshProvider netshProvider,
IConfigFileProvider configFileProvider, IConfigFileProvider configFileProvider,
IRuntimeInfo runtimeInfo, IRuntimeInfo runtimeInfo,
IOsInfo osInfo,
Logger logger) Logger logger)
{ {
_netshProvider = netshProvider; _netshProvider = netshProvider;
_configFileProvider = configFileProvider; _configFileProvider = configFileProvider;
_runtimeInfo = runtimeInfo; _runtimeInfo = runtimeInfo;
_osInfo = osInfo;
_logger = logger; _logger = logger;
InternalUrls = new List<UrlAcl>(); InternalUrls = new List<UrlAcl>();
@ -105,7 +108,8 @@ namespace NzbDrone.Host.AccessControl
private void RefreshRegistration() private void RefreshRegistration()
{ {
if (OsInfo.Version.Major < 6) return; var osVersion = new Version(_osInfo.Version);
if (osVersion.Major < 6) return;
foreach (var urlAcl in InternalUrls) foreach (var urlAcl in InternalUrls)
{ {

View File

@ -51,7 +51,7 @@ namespace NzbDrone.Host
Console.CancelKeyPress += (sender, eventArgs) => LogManager.Configuration = null; Console.CancelKeyPress += (sender, eventArgs) => LogManager.Configuration = null;
} }
_runtimeInfo.IsRunning = true; _runtimeInfo.IsExiting = false;
_hostController.StartServer(); _hostController.StartServer();
if (!_startupContext.Flags.Contains(StartupContext.NO_BROWSER) if (!_startupContext.Flags.Contains(StartupContext.NO_BROWSER)
@ -76,7 +76,7 @@ namespace NzbDrone.Host
_logger.Info("Attempting to stop application."); _logger.Info("Attempting to stop application.");
_hostController.StopServer(); _hostController.StopServer();
_logger.Info("Application has finished stop routine."); _logger.Info("Application has finished stop routine.");
_runtimeInfo.IsRunning = false; _runtimeInfo.IsExiting = true;
} }
public void Handle(ApplicationShutdownRequested message) public void Handle(ApplicationShutdownRequested message)

View File

@ -1,6 +1,5 @@
using System.Threading; using System.Threading;
using NLog; using NLog;
using NLog.Common;
using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Processes; using NzbDrone.Common.Processes;
@ -28,7 +27,7 @@ namespace NzbDrone.Host
public void Spin() public void Spin()
{ {
while (_runtimeInfo.IsRunning) while (!_runtimeInfo.IsExiting)
{ {
Thread.Sleep(1000); Thread.Sleep(1000);
} }

View File

@ -25,7 +25,7 @@ namespace NzbDrone.Integration.Test
protected override void InitializeTestTarget() protected override void InitializeTestTarget()
{ {
// Add Wombles // Add Wombles
var wombles = Indexers.Post(new Api.Indexers.IndexerResource Indexers.Post(new Api.Indexers.IndexerResource
{ {
EnableRss = true, EnableRss = true,
ConfigContract = "NullConfig", ConfigContract = "NullConfig",

View File

@ -0,0 +1,20 @@
using System;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Mono.EnvironmentInfo;
using NzbDrone.Test.Common;
namespace NzbDrone.Mono.Test.EnvironmentInfo
{
[TestFixture]
[Platform("Mono")]
public class MonoPlatformInfoFixture : TestBase<MonoPlatformInfo>
{
[Test]
public void should_get_framework_version()
{
Subject.Version.Major.Should().Be(4);
Subject.Version.Minor.Should().BeOneOf(0, 5, 6);
}
}
}

View File

@ -0,0 +1,29 @@
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Common.Disk;
using NzbDrone.Mono.Disk;
using NzbDrone.Mono.EnvironmentInfo.VersionAdapters;
using NzbDrone.Test.Common;
namespace NzbDrone.Mono.Test.EnvironmentInfo
{
[TestFixture]
[Platform("Mono")]
public class ReleaseFileVersionAdapterFixture : TestBase<ReleaseFileVersionAdapter>
{
[SetUp]
public void Setup()
{
Mocker.SetConstant<IDiskProvider>(Mocker.Resolve<DiskProvider>());
}
[Test]
public void should_get_version_info()
{
var info = Subject.Read();
info.FullName.Should().NotBeNullOrWhiteSpace();
info.Name.Should().NotBeNullOrWhiteSpace();
info.Version.Should().NotBeNullOrWhiteSpace();
}
}
}

View File

@ -0,0 +1,77 @@
using System;
using System.IO;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Common.Disk;
using NzbDrone.Mono.EnvironmentInfo.VersionAdapters;
using NzbDrone.Test.Common;
namespace NzbDrone.Mono.Test.EnvironmentInfo.VersionAdapters
{
[TestFixture]
public class MacOsVersionAdapterFixture : TestBase<MacOsVersionAdapter>
{
[TestCase("10.8.0")]
[TestCase("10.8")]
[TestCase("10.8.1")]
[TestCase("10.11.20")]
public void should_get_version_info(string versionString)
{
var fileContent = File.ReadAllText(GetTestPath("Files/macOS/SystemVersion.plist")).Replace("10.0.0", versionString);
const string plistPath = "/System/Library/CoreServices/SystemVersion.plist";
Mocker.GetMock<IDiskProvider>()
.Setup(c => c.FolderExists("/System/Library/CoreServices/")).Returns(true);
Mocker.GetMock<IDiskProvider>()
.Setup(c => c.GetFiles("/System/Library/CoreServices/", SearchOption.TopDirectoryOnly))
.Returns(new[] { plistPath });
Mocker.GetMock<IDiskProvider>()
.Setup(c => c.ReadAllText(plistPath))
.Returns(fileContent);
var versionName = Subject.Read();
versionName.Version.Should().Be(versionString);
versionName.Name.Should().Be("macOS");
versionName.FullName.Should().Be("macOS " + versionString);
}
[TestCase]
public void should_detect_server()
{
var fileContent = File.ReadAllText(GetTestPath("Files/macOS/SystemVersion.plist"));
const string plistPath = "/System/Library/CoreServices/ServerVersion.plist";
Mocker.GetMock<IDiskProvider>()
.Setup(c => c.FolderExists("/System/Library/CoreServices/")).Returns(true);
Mocker.GetMock<IDiskProvider>()
.Setup(c => c.GetFiles("/System/Library/CoreServices/", SearchOption.TopDirectoryOnly))
.Returns(new[] { plistPath });
Mocker.GetMock<IDiskProvider>()
.Setup(c => c.ReadAllText(plistPath))
.Returns(fileContent);
var versionName = Subject.Read();
versionName.Name.Should().Be("macOS Server");
}
[TestCase]
public void should_return_null_if_folder_doesnt_exist()
{
Mocker.GetMock<IDiskProvider>()
.Setup(c => c.FolderExists("/System/Library/CoreServices/")).Returns(false);
Subject.Read().Should().BeNull();
Mocker.GetMock<IDiskProvider>()
.Verify(c => c.GetFiles(It.IsAny<string>(), SearchOption.TopDirectoryOnly), Times.Never());
}
}
}

View File

@ -0,0 +1,82 @@
using System.IO;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Common.Disk;
using NzbDrone.Mono.Disk;
using NzbDrone.Mono.EnvironmentInfo.VersionAdapters;
using NzbDrone.Test.Common;
using NzbDrone.Test.Common.Categories;
namespace NzbDrone.Mono.Test.EnvironmentInfo.VersionAdapters
{
[TestFixture]
public class ReleaseFileVersionAdapterFixture : TestBase<ReleaseFileVersionAdapter>
{
[Test]
[IntegrationTest]
[Platform("Mono")]
public void should_get_version_info_from_actual_linux()
{
Mocker.SetConstant<IDiskProvider>(Mocker.Resolve<DiskProvider>());
var info = Subject.Read();
info.FullName.Should().NotBeNullOrWhiteSpace();
info.Name.Should().NotBeNullOrWhiteSpace();
info.Version.Should().NotBeNullOrWhiteSpace();
}
[Test]
public void should_return_null_if_etc_doestn_exist()
{
Mocker.GetMock<IDiskProvider>().Setup(c => c.FolderExists("/etc/")).Returns(false);
Subject.Read().Should().BeNull();
Mocker.GetMock<IDiskProvider>()
.Verify(c => c.GetFiles(It.IsAny<string>(), SearchOption.TopDirectoryOnly), Times.Never());
Subject.Read().Should().BeNull();
}
[Test]
public void should_return_null_if_release_file_doestn_exist()
{
Mocker.GetMock<IDiskProvider>().Setup(c => c.FolderExists("/etc/")).Returns(true);
Subject.Read().Should().BeNull();
Mocker.GetMock<IDiskProvider>()
.Setup(c => c.GetFiles(It.IsAny<string>(), SearchOption.TopDirectoryOnly)).Returns(new string[0]);
Subject.Read().Should().BeNull();
}
[Test]
public void should_detect_version()
{
Mocker.GetMock<IDiskProvider>().Setup(c => c.FolderExists("/etc/")).Returns(true);
Subject.Read().Should().BeNull();
Mocker.GetMock<IDiskProvider>()
.Setup(c => c.GetFiles(It.IsAny<string>(), SearchOption.TopDirectoryOnly)).Returns(new[]
{
"/etc/lsb-release",
"/etc/os-release"
});
Mocker.GetMock<IDiskProvider>()
.Setup(c => c.ReadAllText("/etc/lsb-release"))
.Returns(File.ReadAllText(GetTestPath("Files/linux/lsb-release")));
Mocker.GetMock<IDiskProvider>()
.Setup(c => c.ReadAllText("/etc/os-release"))
.Returns(File.ReadAllText(GetTestPath("Files/linux/os-release")));
var version = Subject.Read();
version.Should().NotBeNull();
version.Name.Should().Be("ubuntu");
version.Version.Should().Be("14.04");
version.FullName.Should().Be("Ubuntu 14.04.5 LTS");
}
}
}

View File

@ -0,0 +1,4 @@
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.5 LTS"

View File

@ -0,0 +1,9 @@
NAME="Ubuntu"
VERSION="14.04.5 LTS, Trusty Tahr"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 14.04.5 LTS"
VERSION_ID="14.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>ProductBuildVersion</key>
<string>16C68</string>
<key>ProductCopyright</key>
<string>1983-2016 Apple Inc.</string>
<key>ProductName</key>
<string>Mac OS X</string>
<key>ProductUserVisibleVersion</key>
<string>10.0.0</string>
<key>ProductVersion</key>
<string>10.0.0</string>
</dict>
</plist>

View File

@ -0,0 +1,8 @@
majorversion="6"
minorversion="0"
productversion="6.0.2"
buildphase="hotfix"
buildnumber="8451"
smallfixnumber="7"
builddate="2016/12/20"
buildtime="05:11:44"

View File

@ -81,10 +81,17 @@
<ItemGroup> <ItemGroup>
<Compile Include="DiskProviderTests\DiskProviderFixture.cs" /> <Compile Include="DiskProviderTests\DiskProviderFixture.cs" />
<Compile Include="DiskProviderTests\FreeSpaceFixture.cs" /> <Compile Include="DiskProviderTests\FreeSpaceFixture.cs" />
<Compile Include="EnvironmentInfo\MonoPlatformInfoFixture.cs" />
<Compile Include="EnvironmentInfo\ReleaseFileVersionAdapterFixture.cs" />
<Compile Include="EnvironmentInfo\VersionAdapters\ReleaseFileVersionAdapterFixture.cs" />
<Compile Include="EnvironmentInfo\VersionAdapters\MacOsVersionAdapterFixture.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="app.config" /> <None Include="app.config" />
<None Include="Files\macOS\SystemVersion.plist">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="packages.config" /> <None Include="packages.config" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -116,6 +123,19 @@
<ItemGroup> <ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Include="Files\linux\lsb-release">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<None Include="Files\linux\os-release">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="Files\synology\" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.

View File

@ -0,0 +1,46 @@
using System;
using System.Reflection;
using System.Text.RegularExpressions;
using NLog;
using NzbDrone.Common.EnvironmentInfo;
namespace NzbDrone.Mono.EnvironmentInfo
{
public class MonoPlatformInfo : PlatformInfo
{
private static readonly Regex VersionRegex = new Regex(@"(?<=\W|^)(?<version>\d+\.\d+(\.\d+)?(\.\d+)?)(?=\W)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
public override Version Version { get; }
public MonoPlatformInfo(Logger logger)
{
var runTimeVersion = new Version();
try
{
var type = Type.GetType("Mono.Runtime");
if (type != null)
{
var displayNameMethod = type.GetMethod("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static);
if (displayNameMethod != null)
{
var displayName = displayNameMethod.Invoke(null, null).ToString();
var versionMatch = VersionRegex.Match(displayName);
if (versionMatch.Success)
{
runTimeVersion = new Version(versionMatch.Groups["version"].Value);
}
}
}
}
catch (Exception ex)
{
logger.Error(ex, "Unable to get mono version: " + ex.Message);
}
Version = runTimeVersion;
}
}
}

View File

@ -1,45 +0,0 @@
using System;
using System.Reflection;
using NLog;
using NzbDrone.Common.EnvironmentInfo;
namespace NzbDrone.Mono.EnvironmentInfo
{
public class MonoRuntimeProvider : RuntimeInfoBase
{
private readonly Logger _logger;
public MonoRuntimeProvider(Common.IServiceProvider serviceProvider, Logger logger)
:base(serviceProvider, logger)
{
_logger = logger;
}
public override string RuntimeVersion
{
get
{
try
{
var type = Type.GetType("Mono.Runtime");
if (type != null)
{
var displayName = type.GetMethod("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static);
if (displayName != null)
{
return displayName.Invoke(null, null).ToString();
}
}
}
catch (Exception ex)
{
_logger.Error(ex, "Unable to get mono version: " + ex.Message);
}
return string.Empty;
}
}
}
}

View File

@ -0,0 +1,52 @@
using System.IO;
using System.Linq;
using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo;
namespace NzbDrone.Mono.EnvironmentInfo.VersionAdapters
{
public class IssueFileVersionAdapter : IOsVersionAdapter
{
private readonly IDiskProvider _diskProvider;
public IssueFileVersionAdapter(IDiskProvider diskProvider)
{
_diskProvider = diskProvider;
}
public OsVersionModel Read()
{
if (!_diskProvider.FolderExists("/etc/"))
{
return null;
}
var issueFile = _diskProvider.GetFiles("/etc/", SearchOption.TopDirectoryOnly).SingleOrDefault(c => c.EndsWith("/issue"));
if (issueFile == null)
{
return null;
}
var fileContent = _diskProvider.ReadAllText(issueFile);
// Ubuntu 14.04.5 LTS \n \l
// Ubuntu 16.04.1 LTS \n \l
// Fedora/Centos
// Kernel \r on an \m (\l)
// Arch Linux \r (\l)
// Debian GNU/Linux 8 \n \l
if (fileContent.Contains("Arch Linux"))
{
return new OsVersionModel("Arch", "1.0", "Arch Linux");
}
return null;
}
public bool Enabled => OsInfo.IsLinux;
}
}

View File

@ -0,0 +1,69 @@
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using NLog;
using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo;
namespace NzbDrone.Mono.EnvironmentInfo.VersionAdapters
{
public class MacOsVersionAdapter : IOsVersionAdapter
{
private static readonly Regex DarwinVersionRegex = new Regex("<string>(?<version>10\\.\\d{1,2}\\.?\\d{0,2}?)<\\/string>",
RegexOptions.Compiled |
RegexOptions.IgnoreCase
);
private const string PLIST_DIR = "/System/Library/CoreServices/";
private readonly IDiskProvider _diskProvider;
private readonly Logger _logger;
public MacOsVersionAdapter(IDiskProvider diskProvider, Logger logger)
{
_diskProvider = diskProvider;
_logger = logger;
}
public OsVersionModel Read()
{
var version = "10.0";
if (!_diskProvider.FolderExists(PLIST_DIR))
{
_logger.Debug("Directory {0} doesn't exist", PLIST_DIR);
return null;
}
var allFiles = _diskProvider.GetFiles(PLIST_DIR, SearchOption.TopDirectoryOnly);
var versionFile = allFiles.SingleOrDefault(c =>
c.EndsWith("SystemVersion.plist") ||
c.EndsWith("ServerVersion.plist")
);
if (string.IsNullOrWhiteSpace(versionFile))
{
_logger.Debug("Couldn't find version plist file in {0}", PLIST_DIR);
return null;
}
var text = _diskProvider.ReadAllText(versionFile);
var match = DarwinVersionRegex.Match(text);
if (match.Success)
{
version = match.Groups["version"].Value;
}
var name = versionFile.Contains("Server") ? "macOS Server" : "macOS";
return new OsVersionModel(name, version);
}
public bool Enabled => OsInfo.IsOsx;
}
}

View File

@ -0,0 +1,79 @@
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo;
namespace NzbDrone.Mono.EnvironmentInfo.VersionAdapters
{
public class ReleaseFileVersionAdapter : IOsVersionAdapter
{
private readonly IDiskProvider _diskProvider;
public ReleaseFileVersionAdapter(IDiskProvider diskProvider)
{
_diskProvider = diskProvider;
}
public OsVersionModel Read()
{
if (!_diskProvider.FolderExists("/etc/"))
{
return null;
}
var releaseFiles = _diskProvider.GetFiles("/etc/", SearchOption.TopDirectoryOnly).Where(c => c.EndsWith("release")).ToList();
var name = "Linux";
var fullName = "";
var version = "";
bool success = false;
foreach (var releaseFile in releaseFiles)
{
var fileContent = _diskProvider.ReadAllText(releaseFile);
var lines = Regex.Split(fileContent, "\r\n|\r|\n"); ;
foreach (var line in lines)
{
var parts = line.Split('=');
if (parts.Length >= 2)
{
var key = parts[0];
var value = parts[1];
if (!string.IsNullOrWhiteSpace(value))
{
switch (key)
{
case "ID":
success = true;
name = value;
break;
case "PRETTY_NAME":
success = true;
fullName = value;
break;
case "VERSION_ID":
success = true;
version = value;
break;
}
}
}
}
}
if (!success)
{
return null;
}
return new OsVersionModel(name, version, fullName);
}
public bool Enabled => OsInfo.IsLinux;
}
}

View File

@ -0,0 +1,78 @@
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo;
namespace NzbDrone.Mono.EnvironmentInfo.VersionAdapters
{
public class SynologyVersionAdapter : IOsVersionAdapter
{
private readonly IDiskProvider _diskProvider;
private const string NAME = "DSM";
private const string FULL_NAME = "Synology DSM";
public SynologyVersionAdapter(IDiskProvider diskProvider)
{
_diskProvider = diskProvider;
}
public OsVersionModel Read()
{
if (!_diskProvider.FolderExists("/etc.defaults/"))
{
return null;
}
var versionFile = _diskProvider.GetFiles("/etc.defaults/", SearchOption.TopDirectoryOnly).SingleOrDefault(c => c.EndsWith("VERSION"));
if (versionFile == null)
{
return null;
}
var version = "";
var major = "";
var minor = "0";
var fileContent = _diskProvider.ReadAllText(versionFile);
var lines = Regex.Split(fileContent, "\r\n|\r|\n"); ;
foreach (var line in lines)
{
var parts = line.Split('=');
if (parts.Length >= 2)
{
var key = parts[0];
var value = parts[1];
if (!string.IsNullOrWhiteSpace(value))
{
switch (key)
{
case "productversion":
version = value;
break;
case "majorversion":
major = value;
break;
case "minorversion":
minor = value;
break;
}
}
}
}
if (string.IsNullOrWhiteSpace(version) && !string.IsNullOrWhiteSpace(major))
{
version = $"{major}.{minor}";
}
return new OsVersionModel(NAME, version, $"{FULL_NAME} {version}");
}
public bool Enabled => OsInfo.IsLinux;
}
}

View File

@ -71,9 +71,13 @@
<Compile Include="Disk\DiskProvider.cs" /> <Compile Include="Disk\DiskProvider.cs" />
<Compile Include="Disk\FindDriveType.cs" /> <Compile Include="Disk\FindDriveType.cs" />
<Compile Include="Disk\LinuxPermissionsException.cs" /> <Compile Include="Disk\LinuxPermissionsException.cs" />
<Compile Include="EnvironmentInfo\MonoRuntimeProvider.cs" /> <Compile Include="EnvironmentInfo\VersionAdapters\IssueFileVersionAdapter.cs" />
<Compile Include="EnvironmentInfo\VersionAdapters\MacOsVersionAdapter.cs" />
<Compile Include="EnvironmentInfo\MonoPlatformInfo.cs" />
<Compile Include="Disk\ProcMount.cs" /> <Compile Include="Disk\ProcMount.cs" />
<Compile Include="Disk\ProcMountProvider.cs" /> <Compile Include="Disk\ProcMountProvider.cs" />
<Compile Include="EnvironmentInfo\VersionAdapters\SynologyVersionAdapter.cs" />
<Compile Include="EnvironmentInfo\VersionAdapters\ReleaseFileVersionAdapter.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Disk\SymbolicLinkResolver.cs" /> <Compile Include="Disk\SymbolicLinkResolver.cs" />
</ItemGroup> </ItemGroup>

View File

@ -1,5 +1,3 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
@ -151,7 +149,7 @@ namespace NzbDrone.Test.Common.AutoMoq
private Mock<T> TheRegisteredMockForThisType<T>(Type type) where T : class private Mock<T> TheRegisteredMockForThisType<T>(Type type) where T : class
{ {
return (Mock<T>)_registeredMocks.Where(x => x.Key == type).First().Value; return (Mock<T>)_registeredMocks.First(x => x.Key == type).Value;
} }
private void CreateANewMockAndRegisterIt<T>(Type type, MockBehavior behavior) where T : class private void CreateANewMockAndRegisterIt<T>(Type type, MockBehavior behavior) where T : class

View File

@ -133,7 +133,7 @@ namespace NzbDrone.Test.Common
protected void MonoOnly() protected void MonoOnly()
{ {
if (OsInfo.IsWindows) if (!PlatformInfo.IsMono)
{ {
throw new IgnoreException("mono specific test"); throw new IgnoreException("mono specific test");
} }

View File

@ -24,7 +24,7 @@ namespace NzbDrone.Update.UpdateEngine
{ {
if (OsInfo.IsNotWindows) if (OsInfo.IsNotWindows)
{ {
//Tehcnically its the console, but its been renamed for mono (Linux/OS X) // Technically it is the console, but it has been renamed for mono (Linux/OS X)
return AppType.Normal; return AppType.Normal;
} }

View File

@ -0,0 +1,19 @@
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Test.Common;
using NzbDrone.Windows.EnvironmentInfo;
namespace NzbDrone.Windows.Test.EnvironmentInfo
{
[TestFixture]
[Platform("Win")]
public class DotNetPlatformInfoFixture : TestBase<DotNetPlatformInfo>
{
[Test]
public void should_get_framework_version()
{
Subject.Version.Major.Should().Be(4);
Subject.Version.Minor.Should().BeOneOf(0, 5, 6);
}
}
}

View File

@ -0,0 +1,23 @@
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Test.Common;
using NzbDrone.Windows.EnvironmentInfo;
namespace NzbDrone.Windows.Test.EnvironmentInfo
{
[TestFixture]
[Platform("Win")]
public class WindowsVersionInfoFixture : TestBase<WindowsVersionInfo>
{
[Test]
public void should_get_windows_version()
{
var info = Subject.Read();
info.Version.Should().NotBeNullOrWhiteSpace();
info.Name.Should().Contain("Windows");
info.FullName.Should().Contain("Windows");
info.FullName.Should().Contain("NT");
info.FullName.Should().Contain(info.Version);
}
}
}

View File

@ -73,6 +73,8 @@
<ItemGroup> <ItemGroup>
<Compile Include="DiskProviderTests\DiskProviderFixture.cs" /> <Compile Include="DiskProviderTests\DiskProviderFixture.cs" />
<Compile Include="DiskProviderTests\FreeSpaceFixture.cs" /> <Compile Include="DiskProviderTests\FreeSpaceFixture.cs" />
<Compile Include="EnvironmentInfo\WindowsVersionInfoFixture.cs" />
<Compile Include="EnvironmentInfo\DotNetPlatformInfoFixture.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -0,0 +1,57 @@
using System;
using Microsoft.Win32;
using NzbDrone.Common.EnvironmentInfo;
namespace NzbDrone.Windows.EnvironmentInfo
{
public class DotNetPlatformInfo : PlatformInfo
{
public DotNetPlatformInfo()
{
Version = GetFrameworkVersion();
}
public override Version Version { get; }
private static Version GetFrameworkVersion()
{
const string subkey = @"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\";
using (var ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey(subkey))
{
if (ndpKey == null)
{
return new Version(4, 0);
}
var releaseKey = (int)ndpKey.GetValue("Release");
if (releaseKey >= 394802)
{
return new Version(4,6,2);
}
if (releaseKey >= 394254)
{
return new Version(4,6,1);
}
if (releaseKey >= 393295)
{
return new Version(4,6);
}
if (releaseKey >= 379893)
{
return new Version(4,5,2);
}
if (releaseKey >= 378675)
{
return new Version(4,5,1);
}
if (releaseKey >= 378389)
{
return new Version(4,5);
}
return new Version(4, 0);
}
}
}
}

View File

@ -1,16 +0,0 @@
using System;
using NLog;
using NzbDrone.Common.EnvironmentInfo;
namespace NzbDrone.Windows.EnvironmentInfo
{
public class DotNetRuntimeProvider : RuntimeInfoBase
{
public DotNetRuntimeProvider(Common.IServiceProvider serviceProvider, Logger logger)
: base(serviceProvider, logger)
{
}
public override string RuntimeVersion => Environment.Version.ToString();
}
}

View File

@ -0,0 +1,14 @@
using System;
using NzbDrone.Common.EnvironmentInfo;
namespace NzbDrone.Windows.EnvironmentInfo
{
public class WindowsVersionInfo : IOsVersionAdapter
{
public bool Enabled => OsInfo.IsWindows;
public OsVersionModel Read()
{
return new OsVersionModel("Windows", Environment.OSVersion.Version.ToString(), Environment.OSVersion.VersionString);
}
}
}

View File

@ -64,7 +64,8 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Disk\DiskProvider.cs" /> <Compile Include="Disk\DiskProvider.cs" />
<Compile Include="EnvironmentInfo\DotNetRuntimeProvider.cs" /> <Compile Include="EnvironmentInfo\DotNetPlatformInfo.cs" />
<Compile Include="EnvironmentInfo\WindowsVersionInfo.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -1,7 +1,7 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14 # Visual Studio 14
VisualStudioVersion = 14.0.24720.0 VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{57A04B72-8088-4F75-A582-1158CF8291F7}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{57A04B72-8088-4F75-A582-1158CF8291F7}"
EndProject EndProject

View File

@ -57,8 +57,10 @@
<s:Boolean x:Key="/Default/Environment/InjectedLayers/InjectedLayerCustomization/=File5C7F3FB135E52A44B9447C48B2EEEE92/@KeyIndexDefined">True</s:Boolean> <s:Boolean x:Key="/Default/Environment/InjectedLayers/InjectedLayerCustomization/=File5C7F3FB135E52A44B9447C48B2EEEE92/@KeyIndexDefined">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/InjectedLayers/InjectedLayerCustomization/=File5C7F3FB135E52A44B9447C48B2EEEE92/IsOn/@EntryValue">False</s:Boolean>
<s:Double x:Key="/Default/Environment/InjectedLayers/InjectedLayerCustomization/=File5C7F3FB135E52A44B9447C48B2EEEE92/RelativePriority/@EntryValue">1</s:Double> <s:Double x:Key="/Default/Environment/InjectedLayers/InjectedLayerCustomization/=File5C7F3FB135E52A44B9447C48B2EEEE92/RelativePriority/@EntryValue">1</s:Double>
<s:Boolean x:Key="/Default/Environment/InjectedLayers/InjectedLayerCustomization/=FileEAB6F2886783AB41B46249432F57475A/@KeyIndexDefined">True</s:Boolean> <s:Boolean x:Key="/Default/Environment/InjectedLayers/InjectedLayerCustomization/=FileEAB6F2886783AB41B46249432F57475A/@KeyIndexDefined">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/InjectedLayers/InjectedLayerCustomization/=FileEAB6F2886783AB41B46249432F57475A/IsOn/@EntryValue">False</s:Boolean>
<s:Double x:Key="/Default/Environment/InjectedLayers/InjectedLayerCustomization/=FileEAB6F2886783AB41B46249432F57475A/RelativePriority/@EntryValue">3</s:Double> <s:Double x:Key="/Default/Environment/InjectedLayers/InjectedLayerCustomization/=FileEAB6F2886783AB41B46249432F57475A/RelativePriority/@EntryValue">3</s:Double>