Merge branch 'develop'

This commit is contained in:
Mark McDowall 2014-03-07 23:54:11 -08:00
commit 42501b73a1
191 changed files with 3484 additions and 971 deletions

View File

@ -1,6 +1,7 @@
$msBuild = 'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\msbuild.exe' $msBuild = 'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\msbuild.exe'
$outputFolder = '.\_output' $outputFolder = '.\_output'
$outputFolderMono = '.\_output_mono' $outputFolderMono = '.\_output_mono'
$outputFolderOsx = '.\_output_osx'
$testPackageFolder = '.\_tests\' $testPackageFolder = '.\_tests\'
$testSearchPattern = '*.Test\bin\x86\Release' $testSearchPattern = '*.Test\bin\x86\Release'
$sourceFolder = '.\src' $sourceFolder = '.\src'
@ -112,6 +113,23 @@ Function PackageMono()
Write-Host "##teamcity[progressFinish 'Creating Mono Package']" Write-Host "##teamcity[progressFinish 'Creating Mono Package']"
} }
Function PackageOsx()
{
Write-Host "##teamcity[progressStart 'Creating OS X Package']"
if(Test-Path $outputFolderOsx)
{
Remove-Item -Recurse -Force $outputFolderMono -ErrorAction Continue
}
Copy-Item $outputFolderMono $outputFolderOsx -recurse
Write-Host "Adding sqlite dylibs"
Copy-Item "$sourceFolder\Libraries\sqlite\*.dylib" "$outputFolderOsx"
Write-Host "##teamcity[progressFinish 'Creating OS X Package']"
}
Function AddJsonNet() Function AddJsonNet()
{ {
get-childitem $outputFolder -File -Filter Newtonsoft.Json.* -Recurse | foreach ($_) {remove-item $_.fullname} get-childitem $outputFolder -File -Filter Newtonsoft.Json.* -Recurse | foreach ($_) {remove-item $_.fullname}
@ -187,5 +205,6 @@ Function CleanupWindowsPackage()
Build Build
RunGrunt RunGrunt
PackageMono PackageMono
PackageOsx
PackageTests PackageTests
CleanupWindowsPackage CleanupWindowsPackage

View File

@ -2,7 +2,7 @@
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion> <ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{B1784698-592E-4132-BDFA-9817409E3A96}</ProjectGuid> <ProjectGuid>{B1784698-592E-4132-BDFA-9817409E3A96}</ProjectGuid>
@ -27,24 +27,25 @@
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
<Optimize>false</Optimize>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>..\..\_output\</OutputPath> <OutputPath>..\..\_output\</OutputPath>
<DefineConstants>TRACE</DefineConstants> <DefineConstants>TRACE</DefineConstants>
<DocumentationFile>
</DocumentationFile>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Configuration" /> <Reference Include="System.Configuration" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Web" /> <Reference Include="System.Web" />
<Reference Include="System.XML" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Configuration\ExceptronConfiguration.cs" /> <Compile Include="Configuration\ExceptronConfiguration.cs" />

Binary file not shown.

View File

@ -0,0 +1 @@
libsqlite3.0.dylib

Binary file not shown.

View File

@ -160,6 +160,14 @@ namespace Marr.Data
get { return _children; } get { return _children; }
} }
/// <summary>
/// Adds an Child in the graph for LazyLoaded property.
/// </summary>
public void AddLazyRelationship(Relationship childRelationship)
{
_children.Add(new EntityGraph(childRelationship.RelationshipInfo.EntityType.GetGenericArguments()[0], this, childRelationship));
}
/// <summary> /// <summary>
/// Adds an entity to the appropriate place in the object graph. /// Adds an entity to the appropriate place in the object graph.
/// </summary> /// </summary>
@ -182,7 +190,10 @@ namespace Marr.Data
} }
else // RelationTypes.One else // RelationTypes.One
{ {
_relationship.Setter(_parent._entity, entityInstance); if (_relationship.IsLazyLoaded)
_relationship.Setter(_parent._entity, Activator.CreateInstance(_relationship.MemberType, entityInstance));
else
_relationship.Setter(_parent._entity, entityInstance);
} }
EntityReference entityRef = new EntityReference(entityInstance); EntityReference entityRef = new EntityReference(entityInstance);

View File

@ -2,7 +2,7 @@
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>9.0.30729</ProductVersion> <ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{F6FC6BE7-0847-4817-A1ED-223DC647C3D7}</ProjectGuid> <ProjectGuid>{F6FC6BE7-0847-4817-A1ED-223DC647C3D7}</ProjectGuid>
@ -29,6 +29,8 @@
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
<Optimize>false</Optimize>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>..\..\_output\</OutputPath> <OutputPath>..\..\_output\</OutputPath>
@ -38,11 +40,12 @@
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core"> <Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework> <RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference> </Reference>
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />

View File

@ -551,6 +551,23 @@ namespace Marr.Data.QGen
return Join(joinType, rightMember, filterExpression); return Join(joinType, rightMember, filterExpression);
} }
public virtual QueryBuilder<T> Join<TLeft, TRight>(JoinType joinType, Expression<Func<TLeft, LazyLoaded<TRight>>> rightEntity, Expression<Func<TLeft, TRight, bool>> filterExpression)
{
_isJoin = true;
MemberInfo rightMember = (rightEntity.Body as MemberExpression).Member;
foreach (var item in EntGraph)
{
if (item.EntityType == typeof(TLeft))
{
var relationship = item.Relationships.Single(v => v.Member == rightMember);
item.AddLazyRelationship(relationship);
}
}
return Join(joinType, rightMember, filterExpression);
}
public virtual QueryBuilder<T> Join<TLeft, TRight>(JoinType joinType, MemberInfo rightMember, Expression<Func<TLeft, TRight, bool>> filterExpression) public virtual QueryBuilder<T> Join<TLeft, TRight>(JoinType joinType, MemberInfo rightMember, Expression<Func<TLeft, TRight, bool>> filterExpression)
{ {
_isJoin = true; _isJoin = true;

View File

@ -2,7 +2,7 @@
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion> <ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{1B9A82C4-BCA1-4834-A33E-226F17BE070B}</ProjectGuid> <ProjectGuid>{1B9A82C4-BCA1-4834-A33E-226F17BE070B}</ProjectGuid>
@ -19,7 +19,6 @@
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath> <OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;PERFCOUNTERS</DefineConstants> <DefineConstants>TRACE;DEBUG;PERFCOUNTERS</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Debug\Microsoft.AspNet.SignalR.Core.XML</DocumentationFile> <DocumentationFile>bin\Debug\Microsoft.AspNet.SignalR.Core.XML</DocumentationFile>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<NoWarn>1591</NoWarn> <NoWarn>1591</NoWarn>
@ -27,11 +26,12 @@
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>C:\Dropbox\Git\NzbDrone\src\Common\Microsoft.AspNet.SignalR.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>C:\Dropbox\Git\NzbDrone\src\Common\Microsoft.AspNet.SignalR.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
<Optimize>false</Optimize>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath> <OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE;PERFCOUNTERS</DefineConstants> <DefineConstants>TRACE;PERFCOUNTERS</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>bin\Release\Microsoft.AspNet.SignalR.Core.XML</DocumentationFile> <DocumentationFile>bin\Release\Microsoft.AspNet.SignalR.Core.XML</DocumentationFile>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
@ -40,19 +40,19 @@
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>C:\Dropbox\Git\NzbDrone\src\Common\Microsoft.AspNet.SignalR.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>C:\Dropbox\Git\NzbDrone\src\Common\Microsoft.AspNet.SignalR.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Microsoft.AspNet.SignalR.Client"> <Reference Include="Microsoft.AspNet.SignalR.Client">
<HintPath>..\packages\Microsoft.AspNet.SignalR.Client.1.1.3\lib\net40\Microsoft.AspNet.SignalR.Client.dll</HintPath> <HintPath>..\packages\Microsoft.AspNet.SignalR.Client.1.1.3\lib\net40\Microsoft.AspNet.SignalR.Client.dll</HintPath>
</Reference> </Reference>
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
<Reference Include="System.Security" /> <Reference Include="System.Security" />
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\Common\CommonAssemblyInfo.cs"> <Compile Include="..\Common\CommonAssemblyInfo.cs">
@ -273,8 +273,6 @@
</ItemGroup> </ItemGroup>
<Import Project="..\Common\Microsoft.AspNet.SignalR.targets" /> <Import Project="..\Common\Microsoft.AspNet.SignalR.targets" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="!HasTrailingSlash('$(SolutionDir)')" />
<Import Project="$(SolutionDir).nuget\NuGet.targets" Condition="HasTrailingSlash('$(SolutionDir)')" />
<Target Name="AfterBuild"> <Target Name="AfterBuild">
</Target> </Target>
<!-- 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.

View File

@ -3,7 +3,7 @@
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>{2B8C6DAD-4D85-41B1-83FD-248D9F347522}</ProjectGuid> <ProjectGuid>{2B8C6DAD-4D85-41B1-83FD-248D9F347522}</ProjectGuid>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
@ -14,6 +14,8 @@
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir> <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
<RestorePackages>true</RestorePackages> <RestorePackages>true</RestorePackages>
<TargetFrameworkProfile /> <TargetFrameworkProfile />
<ProductVersion>12.0.0</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
@ -26,6 +28,8 @@
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>C:\Dropbox\Git\NzbDrone\src\Common\Microsoft.AspNet.SignalR.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>C:\Dropbox\Git\NzbDrone\src\Common\Microsoft.AspNet.SignalR.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
<Optimize>false</Optimize>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath> <OutputPath>bin\x86\Release\</OutputPath>
@ -38,15 +42,15 @@
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>C:\Dropbox\Git\NzbDrone\src\Common\Microsoft.AspNet.SignalR.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>C:\Dropbox\Git\NzbDrone\src\Common\Microsoft.AspNet.SignalR.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f585506a2da1fef4, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
<Reference Include="Owin">
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\Common\CommonAssemblyInfo.cs"> <Compile Include="..\Common\CommonAssemblyInfo.cs">
@ -97,8 +101,6 @@
</ItemGroup> </ItemGroup>
<Import Project="..\Common\Microsoft.AspNet.SignalR.targets" /> <Import Project="..\Common\Microsoft.AspNet.SignalR.targets" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="!HasTrailingSlash('$(SolutionDir)')" />
<Import Project="$(SolutionDir).nuget\NuGet.targets" Condition="HasTrailingSlash('$(SolutionDir)')" />
<!-- 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.
<Target Name="BeforeBuild"> <Target Name="BeforeBuild">

View File

@ -3,7 +3,7 @@
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>{D18A5DEB-5102-4775-A1AF-B75DAAA8907B}</ProjectGuid> <ProjectGuid>{D18A5DEB-5102-4775-A1AF-B75DAAA8907B}</ProjectGuid>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
@ -13,6 +13,8 @@
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir> <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages> <RestorePackages>true</RestorePackages>
<ProductVersion>12.0.0</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
@ -22,6 +24,8 @@
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
<Optimize>false</Optimize>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath> <OutputPath>bin\x86\Release\</OutputPath>
@ -31,15 +35,12 @@
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="FizzWare.NBuilder"> <Reference Include="FizzWare.NBuilder">
<HintPath>..\packages\NBuilder.3.0.1.1\lib\FizzWare.NBuilder.dll</HintPath> <HintPath>..\packages\NBuilder.3.0.1.1\lib\FizzWare.NBuilder.dll</HintPath>
</Reference> </Reference>
<Reference Include="FluentAssertions, Version=2.1.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\FluentAssertions.2.1.0.0\lib\net40\FluentAssertions.dll</HintPath>
</Reference>
<Reference Include="Moq"> <Reference Include="Moq">
<HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath> <HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
</Reference> </Reference>
@ -56,6 +57,9 @@
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="FluentAssertions">
<HintPath>..\packages\FluentAssertions.2.1.0.0\lib\net40\FluentAssertions.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="ClientSchemaTests\SchemaBuilderFixture.cs" /> <Compile Include="ClientSchemaTests\SchemaBuilderFixture.cs" />
@ -73,11 +77,11 @@
<Name>NzbDrone.Api</Name> <Name>NzbDrone.Api</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\NzbDrone.Common\NzbDrone.Common.csproj"> <ProjectReference Include="..\NzbDrone.Common\NzbDrone.Common.csproj">
<Project>{f2be0fdf-6e47-4827-a420-dd4ef82407f8}</Project> <Project>{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}</Project>
<Name>NzbDrone.Common</Name> <Name>NzbDrone.Common</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\NzbDrone.Core\NzbDrone.Core.csproj"> <ProjectReference Include="..\NzbDrone.Core\NzbDrone.Core.csproj">
<Project>{ff5ee3b6-913b-47ce-9ceb-11c51b4e1205}</Project> <Project>{FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}</Project>
<Name>NzbDrone.Core</Name> <Name>NzbDrone.Core</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\NzbDrone.Test.Common\NzbDrone.Test.Common.csproj"> <ProjectReference Include="..\NzbDrone.Test.Common\NzbDrone.Test.Common.csproj">

View File

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using NzbDrone.Core.Datastore.Events;
using NzbDrone.Core.HealthCheck;
using NzbDrone.Core.Messaging.Commands;
using NzbDrone.Core.Messaging.Events;
namespace NzbDrone.Api.Health
{
public class HealthModule : NzbDroneRestModuleWithSignalR<HealthResource, HealthCheck>,
IHandle<TriggerHealthCheckEvent>
{
private readonly IHealthCheckService _healthCheckService;
public HealthModule(ICommandExecutor commandExecutor, IHealthCheckService healthCheckService)
: base(commandExecutor)
{
_healthCheckService = healthCheckService;
GetResourceAll = GetHealth;
}
private List<HealthResource> GetHealth()
{
return ToListResource(_healthCheckService.PerformHealthCheck);
}
public void Handle(TriggerHealthCheckEvent message)
{
BroadcastResourceChange(ModelAction.Sync);
}
}
}

View File

@ -0,0 +1,13 @@
using System;
using NzbDrone.Api.REST;
using NzbDrone.Core.HealthCheck;
namespace NzbDrone.Api.Health
{
public class HealthResource : RestResource
{
public HealthCheckResultType Type { get; set; }
public String Message { get; set; }
}
}

View File

@ -39,6 +39,11 @@ namespace NzbDrone.Api.History
pagingSpec.SortKey = "series.title"; pagingSpec.SortKey = "series.title";
} }
if (pagingResource.FilterKey == "eventType")
{
var filterValue = (HistoryEventType)Convert.ToInt32(pagingResource.FilterValue);
pagingSpec.FilterExpression = v => v.EventType == filterValue;
}
if (episodeId.HasValue) if (episodeId.HasValue)
{ {

View File

@ -3,7 +3,7 @@
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>{FD286DF8-2D3A-4394-8AD5-443FADE55FB2}</ProjectGuid> <ProjectGuid>{FD286DF8-2D3A-4394-8AD5-443FADE55FB2}</ProjectGuid>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
@ -15,6 +15,8 @@
<RestorePackages>true</RestorePackages> <RestorePackages>true</RestorePackages>
<TargetFrameworkProfile> <TargetFrameworkProfile>
</TargetFrameworkProfile> </TargetFrameworkProfile>
<ProductVersion>12.0.0</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
@ -24,6 +26,8 @@
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
<Optimize>false</Optimize>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>..\..\_output\</OutputPath> <OutputPath>..\..\_output\</OutputPath>
@ -33,33 +37,32 @@
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup> <WarningLevel>4</WarningLevel>
<PropertyGroup>
<StartupObject />
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="FluentValidation, Version=5.0.0.1, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\FluentValidation.5.0.0.1\lib\Net40\FluentValidation.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AspNet.SignalR.Core, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.AspNet.SignalR.Core, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.AspNet.SignalR.Core.1.1.3\lib\net40\Microsoft.AspNet.SignalR.Core.dll</HintPath> <HintPath>..\packages\Microsoft.AspNet.SignalR.Core.1.1.3\lib\net40\Microsoft.AspNet.SignalR.Core.dll</HintPath>
</Reference> </Reference>
<Reference Include="Nancy, Version=0.21.1.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="Omu.ValueInjecter">
<SpecificVersion>False</SpecificVersion> <HintPath>..\packages\ValueInjecter.2.3.3\lib\net35\Omu.ValueInjecter.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="FluentValidation">
<HintPath>..\packages\FluentValidation.5.0.0.1\lib\Net40\FluentValidation.dll</HintPath>
</Reference>
<Reference Include="Nancy">
<HintPath>..\packages\Nancy.0.21.1\lib\net40\Nancy.dll</HintPath> <HintPath>..\packages\Nancy.0.21.1\lib\net40\Nancy.dll</HintPath>
</Reference> </Reference>
<Reference Include="Nancy.Authentication.Basic, Version=0.21.1.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="Nancy.Authentication.Basic">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Nancy.Authentication.Basic.0.21.1\lib\net40\Nancy.Authentication.Basic.dll</HintPath> <HintPath>..\packages\Nancy.Authentication.Basic.0.21.1\lib\net40\Nancy.Authentication.Basic.dll</HintPath>
</Reference> </Reference>
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> <Reference Include="Newtonsoft.Json">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll</HintPath> <HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference> </Reference>
<Reference Include="NLog, Version=2.1.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL"> <Reference Include="NLog">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath> <HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
</Reference> </Reference>
<Reference Include="Omu.ValueInjecter"> <Reference Include="Omu.ValueInjecter">
@ -129,6 +132,8 @@
<Compile Include="Frontend\Mappers\IMapHttpRequestsToDisk.cs" /> <Compile Include="Frontend\Mappers\IMapHttpRequestsToDisk.cs" />
<Compile Include="Frontend\Mappers\StaticResourceMapperBase.cs" /> <Compile Include="Frontend\Mappers\StaticResourceMapperBase.cs" />
<Compile Include="Frontend\StaticResourceModule.cs" /> <Compile Include="Frontend\StaticResourceModule.cs" />
<Compile Include="Health\HistoryResource.cs" />
<Compile Include="Health\HealthModule.cs" />
<Compile Include="History\HistoryResource.cs" /> <Compile Include="History\HistoryResource.cs" />
<Compile Include="History\HistoryModule.cs" /> <Compile Include="History\HistoryModule.cs" />
<Compile Include="Metadata\MetadataResource.cs" /> <Compile Include="Metadata\MetadataResource.cs" />
@ -150,7 +155,9 @@
<Compile Include="Mapping\MappingValidation.cs" /> <Compile Include="Mapping\MappingValidation.cs" />
<Compile Include="Mapping\ResourceMappingException.cs" /> <Compile Include="Mapping\ResourceMappingException.cs" />
<Compile Include="Mapping\ValueInjectorExtensions.cs" /> <Compile Include="Mapping\ValueInjectorExtensions.cs" />
<Compile Include="Missing\MissingModule.cs" /> <Compile Include="Wanted\CutoffModule.cs" />
<Compile Include="Wanted\LegacyMissingModule.cs" />
<Compile Include="Wanted\MissingModule.cs" />
<Compile Include="Config\NamingSampleResource.cs" /> <Compile Include="Config\NamingSampleResource.cs" />
<Compile Include="NzbDroneRestModuleWithSignalR.cs" /> <Compile Include="NzbDroneRestModuleWithSignalR.cs" />
<Compile Include="Qualities\QualityProfileValidation.cs" /> <Compile Include="Qualities\QualityProfileValidation.cs" />
@ -200,15 +207,15 @@
<Name>Marr.Data</Name> <Name>Marr.Data</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\NzbDrone.Common\NzbDrone.Common.csproj"> <ProjectReference Include="..\NzbDrone.Common\NzbDrone.Common.csproj">
<Project>{f2be0fdf-6e47-4827-a420-dd4ef82407f8}</Project> <Project>{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}</Project>
<Name>NzbDrone.Common</Name> <Name>NzbDrone.Common</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\NzbDrone.Core\NzbDrone.Core.csproj"> <ProjectReference Include="..\NzbDrone.Core\NzbDrone.Core.csproj">
<Project>{ff5ee3b6-913b-47ce-9ceb-11c51b4e1205}</Project> <Project>{FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}</Project>
<Name>NzbDrone.Core</Name> <Name>NzbDrone.Core</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\NzbDrone.SignalR\NzbDrone.SignalR.csproj"> <ProjectReference Include="..\NzbDrone.SignalR\NzbDrone.SignalR.csproj">
<Project>{7c2cc69f-5ca0-4e5c-85cb-983f9f6c3b36}</Project> <Project>{7C2CC69F-5CA0-4E5C-85CB-983F9F6C3B36}</Project>
<Name>NzbDrone.SignalR</Name> <Name>NzbDrone.SignalR</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>

View File

@ -1,6 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.Remoting.Messaging;
using Nancy; using Nancy;
using NzbDrone.Api.Extensions; using NzbDrone.Api.Extensions;
using NzbDrone.Api.Mapping; using NzbDrone.Api.Mapping;

View File

@ -4,6 +4,7 @@ using NzbDrone.Common;
using NzbDrone.Api.Extensions; using NzbDrone.Api.Extensions;
using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Datastore;
namespace NzbDrone.Api.System namespace NzbDrone.Api.System
{ {
@ -13,14 +14,16 @@ namespace NzbDrone.Api.System
private readonly IRuntimeInfo _runtimeInfo; private readonly IRuntimeInfo _runtimeInfo;
private readonly IRouteCacheProvider _routeCacheProvider; private readonly IRouteCacheProvider _routeCacheProvider;
private readonly IConfigFileProvider _configFileProvider; private readonly IConfigFileProvider _configFileProvider;
private readonly IDatabase _database;
public SystemModule(IAppFolderInfo appFolderInfo, IRuntimeInfo runtimeInfo, IRouteCacheProvider routeCacheProvider, IConfigFileProvider configFileProvider) public SystemModule(IAppFolderInfo appFolderInfo, IRuntimeInfo runtimeInfo, IRouteCacheProvider routeCacheProvider, IConfigFileProvider configFileProvider, IDatabase database)
: base("system") : base("system")
{ {
_appFolderInfo = appFolderInfo; _appFolderInfo = appFolderInfo;
_runtimeInfo = runtimeInfo; _runtimeInfo = runtimeInfo;
_routeCacheProvider = routeCacheProvider; _routeCacheProvider = routeCacheProvider;
_configFileProvider = configFileProvider; _configFileProvider = configFileProvider;
_database = database;
Get["/status"] = x => GetStatus(); Get["/status"] = x => GetStatus();
Get["/routes"] = x => GetRoutes(); Get["/routes"] = x => GetRoutes();
} }
@ -44,6 +47,7 @@ namespace NzbDrone.Api.System
Branch = _configFileProvider.Branch, Branch = _configFileProvider.Branch,
Authentication = _configFileProvider.AuthenticationEnabled, Authentication = _configFileProvider.AuthenticationEnabled,
StartOfWeek = (int)OsInfo.FirstDayOfWeek, StartOfWeek = (int)OsInfo.FirstDayOfWeek,
SqliteVersion = _database.Version,
UrlBase = _configFileProvider.UrlBase UrlBase = _configFileProvider.UrlBase
}.AsResponse(); }.AsResponse();

View File

@ -0,0 +1,48 @@
using System.Linq;
using NzbDrone.Api.Episodes;
using NzbDrone.Api.Extensions;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Tv;
namespace NzbDrone.Api.Wanted
{
public class CutoffModule : NzbDroneRestModule<EpisodeResource>
{
private readonly IEpisodeCutoffService _episodeCutoffService;
private readonly SeriesRepository _seriesRepository;
public CutoffModule(IEpisodeCutoffService episodeCutoffService, SeriesRepository seriesRepository)
:base("wanted/cutoff")
{
_episodeCutoffService = episodeCutoffService;
_seriesRepository = seriesRepository;
GetResourcePaged = GetCutoffUnmetEpisodes;
}
private PagingResource<EpisodeResource> GetCutoffUnmetEpisodes(PagingResource<EpisodeResource> pagingResource)
{
var pagingSpec = new PagingSpec<Episode>
{
Page = pagingResource.Page,
PageSize = pagingResource.PageSize,
SortKey = pagingResource.SortKey,
SortDirection = pagingResource.SortDirection
};
if (pagingResource.FilterKey == "monitored" && pagingResource.FilterValue == "false")
{
pagingSpec.FilterExpression = v => v.Monitored == false || v.Series.Monitored == false;
}
else
{
pagingSpec.FilterExpression = v => v.Monitored == true && v.Series.Monitored == true;
}
PagingResource<EpisodeResource> resource = ApplyToPage(_episodeCutoffService.EpisodesWhereCutoffUnmet, pagingSpec);
resource.Records = resource.Records.LoadSubtype(e => e.SeriesId, _seriesRepository).ToList();
return resource;
}
}
}

View File

@ -0,0 +1,34 @@
using System;
using System.Text;
using Nancy;
namespace NzbDrone.Api.Wanted
{
class LegacyMissingModule : NzbDroneApiModule
{
public LegacyMissingModule() : base("missing")
{
Get["/"] = x =>
{
string queryString = ConvertQueryParams(Request.Query);
var url = String.Format("/api/wanted/missing?{0}", queryString);
return Response.AsRedirect(url);
};
}
private string ConvertQueryParams(DynamicDictionary query)
{
var sb = new StringBuilder();
foreach (var key in query)
{
var value = query[key];
sb.AppendFormat("&{0}={1}", key, value);
}
return sb.ToString().Trim('&');
}
}
}

View File

@ -4,7 +4,7 @@ using NzbDrone.Api.Extensions;
using NzbDrone.Core.Datastore; using NzbDrone.Core.Datastore;
using NzbDrone.Core.Tv; using NzbDrone.Core.Tv;
namespace NzbDrone.Api.Missing namespace NzbDrone.Api.Wanted
{ {
public class MissingModule : NzbDroneRestModule<EpisodeResource> public class MissingModule : NzbDroneRestModule<EpisodeResource>
{ {
@ -12,7 +12,7 @@ namespace NzbDrone.Api.Missing
private readonly SeriesRepository _seriesRepository; private readonly SeriesRepository _seriesRepository;
public MissingModule(IEpisodeService episodeService, SeriesRepository seriesRepository) public MissingModule(IEpisodeService episodeService, SeriesRepository seriesRepository)
:base("missing") :base("wanted/missing")
{ {
_episodeService = episodeService; _episodeService = episodeService;
_seriesRepository = seriesRepository; _seriesRepository = seriesRepository;
@ -29,7 +29,17 @@ namespace NzbDrone.Api.Missing
SortDirection = pagingResource.SortDirection SortDirection = pagingResource.SortDirection
}; };
var resource = ApplyToPage(_episodeService.EpisodesWithoutFiles, pagingSpec); if (pagingResource.FilterKey == "monitored" && pagingResource.FilterValue == "false")
{
pagingSpec.FilterExpression = v => v.Monitored == false || v.Series.Monitored == false;
}
else
{
pagingSpec.FilterExpression = v => v.Monitored == true && v.Series.Monitored == true;
}
PagingResource<EpisodeResource> resource = ApplyToPage(v => _episodeService.EpisodesWithoutFiles(v), pagingSpec);
resource.Records = resource.Records.LoadSubtype(e => e.SeriesId, _seriesRepository).ToList(); resource.Records = resource.Records.LoadSubtype(e => e.SeriesId, _seriesRepository).ToList();
return resource; return resource;

View File

@ -2,7 +2,7 @@
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion> <ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}</ProjectGuid> <ProjectGuid>{C0EA1A40-91AD-4EEB-BD16-2DDDEBD20AE5}</ProjectGuid>
@ -23,6 +23,8 @@
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
<Optimize>false</Optimize>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath> <OutputPath>bin\x86\Release\</OutputPath>
@ -32,31 +34,29 @@
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="FizzWare.NBuilder, Version=3.0.1.0, Culture=neutral, PublicKeyToken=5651b03e12e42c12, processorArchitecture=MSIL">
<HintPath>..\packages\NBuilder.3.0.1.1\lib\FizzWare.NBuilder.dll</HintPath>
</Reference>
<Reference Include="FluentAssertions, Version=2.1.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\FluentAssertions.2.1.0.0\lib\net40\FluentAssertions.dll</HintPath>
</Reference>
<Reference Include="Moq"> <Reference Include="Moq">
<HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath> <HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
</Reference> </Reference>
<Reference Include="NLog, Version=2.1.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
</Reference>
<Reference Include="nunit.framework, Version=2.6.2.12296, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\NUnit.2.6.2\lib\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.ServiceProcess" /> <Reference Include="System.ServiceProcess" />
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="FizzWare.NBuilder, Version=3.0.1.0, Culture=neutral, PublicKeyToken=5651b03e12e42c12">
<HintPath>..\packages\NBuilder.3.0.1.1\lib\FizzWare.NBuilder.dll</HintPath>
</Reference>
<Reference Include="FluentAssertions">
<HintPath>..\packages\FluentAssertions.2.1.0.0\lib\net40\FluentAssertions.dll</HintPath>
</Reference>
<Reference Include="NLog">
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
</Reference>
<Reference Include="nunit.framework">
<HintPath>..\packages\NUnit.2.6.2\lib\nunit.framework.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="ContainerFixture.cs" /> <Compile Include="ContainerFixture.cs" />
@ -77,7 +77,7 @@
<Name>NzbDrone.Common</Name> <Name>NzbDrone.Common</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\NzbDrone.Core\NzbDrone.Core.csproj"> <ProjectReference Include="..\NzbDrone.Core\NzbDrone.Core.csproj">
<Project>{ff5ee3b6-913b-47ce-9ceb-11c51b4e1205}</Project> <Project>{FF5EE3B6-913B-47CE-9CEB-11C51B4E1205}</Project>
<Name>NzbDrone.Core</Name> <Name>NzbDrone.Core</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\NzbDrone.Host\NzbDrone.Host.csproj"> <ProjectReference Include="..\NzbDrone.Host\NzbDrone.Host.csproj">

View File

@ -45,12 +45,12 @@ namespace NzbDrone.Automation.Test
} }
[Test] [Test]
public void missing_page() public void wanted_page()
{ {
page.MissingNavIcon.Click(); page.WantedNavIcon.Click();
page.WaitForNoSpinner(); page.WaitForNoSpinner();
page.FindByClass("iv-missing-missinglayout").Should().NotBeNull(); page.FindByClass("iv-wanted-missing-missinglayout").Should().NotBeNull();
} }
[Test] [Test]

View File

@ -3,7 +3,7 @@
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>{CC26800D-F67E-464B-88DE-8EB1A0C227A3}</ProjectGuid> <ProjectGuid>{CC26800D-F67E-464B-88DE-8EB1A0C227A3}</ProjectGuid>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
@ -13,6 +13,8 @@
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir> <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages> <RestorePackages>true</RestorePackages>
<ProductVersion>12.0.0</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
@ -22,6 +24,8 @@
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
<Optimize>false</Optimize>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath> <OutputPath>bin\x86\Release\</OutputPath>
@ -31,12 +35,9 @@
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="FluentAssertions, Version=2.1.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\FluentAssertions.2.1.0.0\lib\net40\FluentAssertions.dll</HintPath>
</Reference>
<Reference Include="NLog"> <Reference Include="NLog">
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath> <HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
</Reference> </Reference>
@ -57,6 +58,9 @@
<Reference Include="WebDriver.Support"> <Reference Include="WebDriver.Support">
<HintPath>..\packages\Selenium.Support.2.37.0\lib\net40\WebDriver.Support.dll</HintPath> <HintPath>..\packages\Selenium.Support.2.37.0\lib\net40\WebDriver.Support.dll</HintPath>
</Reference> </Reference>
<Reference Include="FluentAssertions">
<HintPath>..\packages\FluentAssertions.2.1.0.0\lib\net40\FluentAssertions.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="AutomationTestAttribute.cs" /> <Compile Include="AutomationTestAttribute.cs" />

View File

@ -72,11 +72,11 @@ namespace NzbDrone.Automation.Test.PageModel
} }
} }
public IWebElement MissingNavIcon public IWebElement WantedNavIcon
{ {
get get
{ {
return Find(By.LinkText("Missing")); return Find(By.LinkText("Wanted"));
} }
} }
@ -92,7 +92,7 @@ namespace NzbDrone.Automation.Test.PageModel
{ {
get get
{ {
return Find(By.LinkText("System")); return Find(By.PartialLinkText("System"));
} }
} }

View File

@ -2,7 +2,7 @@
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion> <ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{BEC74619-DDBB-4FBA-B517-D3E20AFC9997}</ProjectGuid> <ProjectGuid>{BEC74619-DDBB-4FBA-B517-D3E20AFC9997}</ProjectGuid>
@ -23,6 +23,8 @@
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
<Optimize>false</Optimize>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath> <OutputPath>bin\x86\Release\</OutputPath>
@ -32,23 +34,12 @@
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="FluentAssertions, Version=2.1.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\FluentAssertions.2.1.0.0\lib\net40\FluentAssertions.dll</HintPath>
</Reference>
<Reference Include="Moq"> <Reference Include="Moq">
<HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath> <HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
</Reference> </Reference>
<Reference Include="NLog, Version=2.1.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
</Reference>
<Reference Include="nunit.framework, Version=2.6.2.12296, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\NUnit.2.6.2\lib\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.ServiceProcess" /> <Reference Include="System.ServiceProcess" />
@ -57,6 +48,15 @@
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="FluentAssertions">
<HintPath>..\packages\FluentAssertions.2.1.0.0\lib\net40\FluentAssertions.dll</HintPath>
</Reference>
<Reference Include="NLog">
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
</Reference>
<Reference Include="nunit.framework">
<HintPath>..\packages\NUnit.2.6.2\lib\nunit.framework.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="CacheTests\CachedManagerFixture.cs" /> <Compile Include="CacheTests\CachedManagerFixture.cs" />

View File

@ -24,8 +24,6 @@ namespace NzbDrone.Common.Composition
_container.Register<TService, TImplementation>(); _container.Register<TService, TImplementation>();
} }
public TinyIoCContainer TinyContainer { get { return _container; } }
public void Register<T>(T instance) where T : class public void Register<T>(T instance) where T : class
{ {
_container.Register<T>(instance); _container.Register<T>(instance);
@ -48,22 +46,7 @@ namespace NzbDrone.Common.Composition
public void Register<TService>(Func<IContainer, TService> factory) where TService : class public void Register<TService>(Func<IContainer, TService> factory) where TService : class
{ {
_container.Register((c, n) => _container.Register((c, n) => factory(this));
{
return factory(this);
});
}
public void RegisterSingleton<TService, TImplementation>()
where TImplementation : class, TService
where TService : class
{
_container.Register<TService, TImplementation>().AsSingleton();
}
public void RegisterSingleton<T>() where T : class
{
_container.Register<T, T>().AsSingleton();
} }
public void RegisterSingleton(Type service, Type implementation) public void RegisterSingleton(Type service, Type implementation)
@ -76,16 +59,6 @@ namespace NzbDrone.Common.Composition
return _container.ResolveAll<T>(); return _container.ResolveAll<T>();
} }
public IEnumerable<object> ResolveAll(Type type)
{
return _container.ResolveAll(type);
}
public void Register(Type registrationType, object instance)
{
_container.Register(registrationType, instance);
}
public void RegisterAllAsSingleton(Type registrationType, IEnumerable<Type> implementationList) public void RegisterAllAsSingleton(Type registrationType, IEnumerable<Type> implementationList)
{ {
_container.RegisterMultiple(registrationType, implementationList).AsSingleton(); _container.RegisterMultiple(registrationType, implementationList).AsSingleton();

View File

@ -6,7 +6,6 @@ namespace NzbDrone.Common.Composition
{ {
public interface IContainer public interface IContainer
{ {
TinyIoCContainer TinyContainer { get; }
void Register<T>(T instance) where T : class; void Register<T>(T instance) where T : class;
void Register<TService, TImplementation>() void Register<TService, TImplementation>()
@ -16,14 +15,8 @@ namespace NzbDrone.Common.Composition
object Resolve(Type type); object Resolve(Type type);
void Register(Type serviceType, Type implementationType); void Register(Type serviceType, Type implementationType);
void Register<TService>(Func<IContainer, TService> factory) where TService : class; void Register<TService>(Func<IContainer, TService> factory) where TService : class;
void RegisterSingleton<TService, TImplementation>()
where TImplementation : class, TService
where TService : class;
void RegisterSingleton<T>() where T : class;
void RegisterSingleton(Type service, Type implementation); void RegisterSingleton(Type service, Type implementation);
IEnumerable<T> ResolveAll<T>() where T : class; IEnumerable<T> ResolveAll<T>() where T : class;
IEnumerable<object> ResolveAll(Type type);
void Register(Type registrationType, object instance);
void RegisterAllAsSingleton(Type registrationType, IEnumerable<Type> implementationList); void RegisterAllAsSingleton(Type registrationType, IEnumerable<Type> implementationList);
bool IsTypeRegistered(Type type); bool IsTypeRegistered(Type type);

View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace NzbDrone.Common
{
public static class DictionaryExtensions
{
public static TValue GetValueOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue = default(TValue))
{
TValue value;
return dictionary.TryGetValue(key, out value) ? value : defaultValue;
}
}
}

View File

@ -365,11 +365,6 @@ namespace NzbDrone.Common.Disk
} }
public void SetFolderWriteTime(string path, DateTime time)
{
Directory.SetLastWriteTimeUtc(path, time);
}
private static void RemoveReadOnly(string path) private static void RemoveReadOnly(string path)
{ {
if (File.Exists(path)) if (File.Exists(path))

View File

@ -37,7 +37,6 @@ namespace NzbDrone.Common.Disk
string GetPathRoot(string path); string GetPathRoot(string path);
string GetParentFolder(string path); string GetParentFolder(string path);
void SetPermissions(string filename, WellKnownSidType accountSid, FileSystemRights rights, AccessControlType controlType); void SetPermissions(string filename, WellKnownSidType accountSid, FileSystemRights rights, AccessControlType controlType);
void SetFolderWriteTime(string path, DateTime time);
FileAttributes GetFileAttributes(string path); FileAttributes GetFileAttributes(string path);
void EmptyFolder(string path); void EmptyFolder(string path);
string[] GetFixedDrives(); string[] GetFixedDrives();

View File

@ -2,7 +2,7 @@
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion> <ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}</ProjectGuid> <ProjectGuid>{F2BE0FDF-6E47-4827-A420-DD4EF82407F8}</ProjectGuid>
@ -25,6 +25,8 @@
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
<Optimize>false</Optimize>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>..\..\_output\</OutputPath> <OutputPath>..\..\_output\</OutputPath>
@ -34,29 +36,27 @@
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="ICSharpCode.SharpZipLib"> <Reference Include="ICSharpCode.SharpZipLib">
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath> <HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
</Reference> </Reference>
<Reference Include="Loggly, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\loggly-csharp.2.3\lib\net35\Loggly.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NLog, Version=2.1.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Configuration" /> <Reference Include="System.Configuration" />
<Reference Include="System.Configuration.Install" /> <Reference Include="System.Configuration.Install" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.ServiceProcess" /> <Reference Include="System.ServiceProcess" />
<Reference Include="Loggly">
<HintPath>..\packages\loggly-csharp.2.3\lib\net35\Loggly.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NLog">
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="ArchiveProvider.cs" /> <Compile Include="ArchiveProvider.cs" />
@ -67,6 +67,7 @@
<Compile Include="Composition\IContainer.cs" /> <Compile Include="Composition\IContainer.cs" />
<Compile Include="Composition\ContainerBuilderBase.cs" /> <Compile Include="Composition\ContainerBuilderBase.cs" />
<Compile Include="DateTimeExtensions.cs" /> <Compile Include="DateTimeExtensions.cs" />
<Compile Include="DictionaryExtensions.cs" />
<Compile Include="Disk\DiskProviderBase.cs" /> <Compile Include="Disk\DiskProviderBase.cs" />
<Compile Include="EnsureThat\Ensure.cs" /> <Compile Include="EnsureThat\Ensure.cs" />
<Compile Include="EnsureThat\EnsureBoolExtensions.cs" /> <Compile Include="EnsureThat\EnsureBoolExtensions.cs" />

View File

@ -52,5 +52,10 @@ namespace NzbDrone.Common
{ {
return CollapseSpace.Replace(text, " ").Trim(); return CollapseSpace.Replace(text, " ").Trim();
} }
public static bool IsNullOrWhiteSpace(this string text)
{
return String.IsNullOrWhiteSpace(text);
}
} }
} }

View File

@ -63,28 +63,23 @@
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent> <RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Microsoft.Owin, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.1.1.0-beta2\lib\net40\Microsoft.Owin.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Owin.Hosting, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.Hosting.1.1.0-beta2\lib\net40\Microsoft.Owin.Hosting.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NLog, Version=2.1.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
</Reference>
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="Microsoft.Owin">
<HintPath>..\packages\Microsoft.Owin.1.1.0-beta2\lib\net40\Microsoft.Owin.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Owin.Hosting">
<HintPath>..\packages\Microsoft.Owin.Hosting.1.1.0-beta2\lib\net40\Microsoft.Owin.Hosting.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NLog">
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
</Reference>
<Reference Include="Owin">
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\NzbDrone.Common\Properties\SharedAssemblyInfo.cs"> <Compile Include="..\NzbDrone.Common\Properties\SharedAssemblyInfo.cs">
@ -118,11 +113,11 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Microsoft.AspNet.SignalR.Core\Microsoft.AspNet.SignalR.Core.csproj"> <ProjectReference Include="..\Microsoft.AspNet.SignalR.Core\Microsoft.AspNet.SignalR.Core.csproj">
<Project>{1b9a82c4-bca1-4834-a33e-226f17be070b}</Project> <Project>{1B9A82C4-BCA1-4834-A33E-226F17BE070B}</Project>
<Name>Microsoft.AspNet.SignalR.Core</Name> <Name>Microsoft.AspNet.SignalR.Core</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\Microsoft.AspNet.SignalR.Owin\Microsoft.AspNet.SignalR.Owin.csproj"> <ProjectReference Include="..\Microsoft.AspNet.SignalR.Owin\Microsoft.AspNet.SignalR.Owin.csproj">
<Project>{2b8c6dad-4d85-41b1-83fd-248d9f347522}</Project> <Project>{2B8C6DAD-4D85-41B1-83FD-248D9F347522}</Project>
<Name>Microsoft.AspNet.SignalR.Owin</Name> <Name>Microsoft.AspNet.SignalR.Owin</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\NzbDrone.Common\NzbDrone.Common.csproj"> <ProjectReference Include="..\NzbDrone.Common\NzbDrone.Common.csproj">
@ -130,7 +125,7 @@
<Name>NzbDrone.Common</Name> <Name>NzbDrone.Common</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\NzbDrone.Host\NzbDrone.Host.csproj"> <ProjectReference Include="..\NzbDrone.Host\NzbDrone.Host.csproj">
<Project>{95c11a9e-56ed-456a-8447-2c89c1139266}</Project> <Project>{95C11A9E-56ED-456A-8447-2C89C1139266}</Project>
<Name>NzbDrone.Host</Name> <Name>NzbDrone.Host</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
@ -145,9 +140,6 @@
<PreBuildEvent> <PreBuildEvent>
</PreBuildEvent> </PreBuildEvent>
</PropertyGroup> </PropertyGroup>
<PropertyGroup>
<PostBuildEvent>xcopy /s /y "$(SolutionDir)\Libraries\Sqlite\*.*" "$(TargetDir)"</PostBuildEvent>
</PropertyGroup>
<Import Project="$(SolutionDir)\.nuget\nuget.targets" /> <Import Project="$(SolutionDir)\.nuget\nuget.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

@ -21,7 +21,7 @@ namespace NzbDrone.Core.Test.Blacklisting
_blacklist = new Blacklist _blacklist = new Blacklist
{ {
SeriesId = 12345, SeriesId = 12345,
EpisodeIds = new List<int> {1}, EpisodeIds = new List<int> { 1 },
Quality = new QualityModel(Quality.Bluray720p), Quality = new QualityModel(Quality.Bluray720p),
SourceTitle = "series.title.s01e01", SourceTitle = "series.title.s01e01",
Date = DateTime.UtcNow Date = DateTime.UtcNow
@ -48,7 +48,7 @@ namespace NzbDrone.Core.Test.Blacklisting
{ {
Subject.Insert(_blacklist); Subject.Insert(_blacklist);
Subject.Blacklisted(_blacklist.SourceTitle.ToUpperInvariant()).Should().BeTrue(); Subject.Blacklisted(_blacklist.SeriesId, _blacklist.SourceTitle.ToUpperInvariant()).Should().BeTrue();
} }
} }
} }

View File

@ -35,7 +35,7 @@ namespace NzbDrone.Core.Test.DataAugmentationFixture.Scene
_fakeMappings[4].ParseTerm = "Cleaned"; _fakeMappings[4].ParseTerm = "Cleaned";
} }
[Test] [Test]
public void UpdateMappings_purge_existing_mapping_and_add_new_ones() public void UpdateMappings_purge_existing_mapping_and_add_new_ones()
@ -80,14 +80,14 @@ namespace NzbDrone.Core.Test.DataAugmentationFixture.Scene
private void AssertNoUpdate() private void AssertNoUpdate()
{ {
Mocker.GetMock<ISceneMappingProxy>().Verify(c => c.Fetch(), Times.Once()); Mocker.GetMock<ISceneMappingProxy>().Verify(c => c.Fetch(), Times.Once());
Mocker.GetMock<ISceneMappingRepository>().Verify(c => c.Purge(), Times.Never()); Mocker.GetMock<ISceneMappingRepository>().Verify(c => c.Purge(It.IsAny<bool>()), Times.Never());
Mocker.GetMock<ISceneMappingRepository>().Verify(c => c.InsertMany(_fakeMappings), Times.Never()); Mocker.GetMock<ISceneMappingRepository>().Verify(c => c.InsertMany(_fakeMappings), Times.Never());
} }
private void AssertMappingUpdated() private void AssertMappingUpdated()
{ {
Mocker.GetMock<ISceneMappingProxy>().Verify(c => c.Fetch(), Times.Once()); Mocker.GetMock<ISceneMappingProxy>().Verify(c => c.Fetch(), Times.Once());
Mocker.GetMock<ISceneMappingRepository>().Verify(c => c.Purge(), Times.Once()); Mocker.GetMock<ISceneMappingRepository>().Verify(c => c.Purge(It.IsAny<bool>()), Times.Once());
Mocker.GetMock<ISceneMappingRepository>().Verify(c => c.InsertMany(_fakeMappings), Times.Once()); Mocker.GetMock<ISceneMappingRepository>().Verify(c => c.InsertMany(_fakeMappings), Times.Once());

View File

@ -0,0 +1,36 @@
using System;
using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Test.Datastore
{
public class DatabaseFixture : DbTest
{
[Test]
public void SingleOrDefault_should_return_null_on_empty_db()
{
Mocker.Resolve<IDatabase>()
.GetDataMapper().Query<Series>()
.SingleOrDefault(c => c.CleanTitle == "SomeTitle")
.Should()
.BeNull();
}
[Test]
public void vaccume()
{
Mocker.Resolve<IDatabase>().Vacuum();
}
[Test]
public void get_version()
{
Mocker.Resolve<IDatabase>().Version.Should().BeGreaterThan(new Version("3.0.0"));
}
}
}

View File

@ -5,6 +5,7 @@ using Marr.Data;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Core.Datastore; using NzbDrone.Core.Datastore;
using NzbDrone.Core.Datastore.Converters; using NzbDrone.Core.Datastore.Converters;
using NzbDrone.Core.Datastore.Extentions;
using NzbDrone.Core.Tv; using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Test.Datastore namespace NzbDrone.Core.Test.Datastore

View File

@ -0,0 +1,105 @@
using FizzWare.NBuilder;
using NUnit.Framework;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.MediaFiles;
namespace NzbDrone.Core.Test.Datastore
{
[TestFixture]
public class MarrDataLazyLoadingFixture : DbTest
{
[SetUp]
public void Setup()
{
var qualityProfile = new NzbDrone.Core.Qualities.QualityProfile
{
Name = "Test",
Cutoff = Quality.WEBDL720p,
Items = NzbDrone.Core.Test.Qualities.QualityFixture.GetDefaultQualities()
};
qualityProfile = Db.Insert(qualityProfile);
var series = Builder<Series>.CreateListOfSize(1)
.All()
.With(v => v.QualityProfileId = qualityProfile.Id)
.BuildListOfNew();
Db.InsertMany(series);
var episodeFiles = Builder<EpisodeFile>.CreateListOfSize(1)
.All()
.With(v => v.SeriesId = series[0].Id)
.BuildListOfNew();
Db.InsertMany(episodeFiles);
var episodes = Builder<Episode>.CreateListOfSize(10)
.All()
.With(v => v.Monitored = true)
.With(v => v.EpisodeFileId = episodeFiles[0].Id)
.With(v => v.SeriesId = series[0].Id)
.BuildListOfNew();
Db.InsertMany(episodes);
}
[Test]
public void should_lazy_load_qualityprofile_if_not_joined()
{
var db = Mocker.Resolve<IDatabase>();
var DataMapper = db.GetDataMapper();
var episodes = DataMapper.Query<Episode>()
.Join<Episode, Series>(Marr.Data.QGen.JoinType.Inner, v => v.Series, (l, r) => l.SeriesId == r.Id)
.ToList();
foreach (var episode in episodes)
{
Assert.IsNotNull(episode.Series);
Assert.IsFalse(episode.Series.QualityProfile.IsLoaded);
}
}
[Test]
public void should_explicit_load_episodefile_if_joined()
{
var db = Mocker.Resolve<IDatabase>();
var DataMapper = db.GetDataMapper();
var episodes = DataMapper.Query<Episode>()
.Join<Episode, EpisodeFile>(Marr.Data.QGen.JoinType.Inner, v => v.EpisodeFile, (l, r) => l.EpisodeFileId == r.Id)
.ToList();
foreach (var episode in episodes)
{
Assert.IsNull(episode.Series);
Assert.IsTrue(episode.EpisodeFile.IsLoaded);
}
}
[Test]
public void should_explicit_load_qualityprofile_if_joined()
{
var db = Mocker.Resolve<IDatabase>();
var DataMapper = db.GetDataMapper();
var episodes = DataMapper.Query<Episode>()
.Join<Episode, Series>(Marr.Data.QGen.JoinType.Inner, v => v.Series, (l, r) => l.SeriesId == r.Id)
.Join<Series, QualityProfile>(Marr.Data.QGen.JoinType.Inner, v => v.QualityProfile, (l, r) => l.QualityProfileId == r.Id)
.ToList();
foreach (var episode in episodes)
{
Assert.IsNotNull(episode.Series);
Assert.IsTrue(episode.Series.QualityProfile.IsLoaded);
}
}
}
}

View File

@ -7,24 +7,9 @@ using NUnit.Framework;
using NzbDrone.Core.Datastore; using NzbDrone.Core.Datastore;
using NzbDrone.Core.Jobs; using NzbDrone.Core.Jobs;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Test.Datastore namespace NzbDrone.Core.Test.Datastore
{ {
public class DatabaseFixture : DbTest
{
[Test]
public void SingleOrDefault_should_return_null_on_empty_db()
{
Mocker.Resolve<IDatabase>()
.GetDataMapper().Query<Series>()
.SingleOrDefault(c => c.CleanTitle == "SomeTitle")
.Should()
.BeNull();
}
}
[TestFixture] [TestFixture]
public class ObjectDatabaseFixture : DbTest<BasicRepository<ScheduledTask>, ScheduledTask> public class ObjectDatabaseFixture : DbTest<BasicRepository<ScheduledTask>, ScheduledTask>
{ {

View File

@ -1,6 +1,7 @@
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Core.Datastore; using NzbDrone.Core.Datastore;
using NzbDrone.Core.Datastore.Extentions;
using NzbDrone.Core.Tv; using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Test.Datastore.PagingSpecExtenstionsTests namespace NzbDrone.Core.Test.Datastore.PagingSpecExtenstionsTests

View File

@ -1,6 +1,7 @@
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Core.Datastore; using NzbDrone.Core.Datastore;
using NzbDrone.Core.Datastore.Extentions;
using NzbDrone.Core.Tv; using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Test.Datastore.PagingSpecExtenstionsTests namespace NzbDrone.Core.Test.Datastore.PagingSpecExtenstionsTests

View File

@ -131,6 +131,54 @@ namespace NzbDrone.Core.Test.Download
VerifyNoFailedDownloads(); VerifyNoFailedDownloads();
} }
[Test]
public void should_not_process_if_grabbed_history_contains_null_downloadclient_id()
{
GivenFailedDownloadClientHistory();
var historyGrabbed = Builder<History.History>.CreateListOfSize(1)
.Build()
.ToList();
historyGrabbed.First().Data.Add("downloadClient", "SabnzbdClient");
historyGrabbed.First().Data.Add("downloadClientId", null);
GivenGrabbedHistory(historyGrabbed);
GivenNoFailedHistory();
Subject.Execute(new CheckForFailedDownloadCommand());
VerifyNoFailedDownloads();
}
[Test]
public void should_process_if_failed_history_contains_null_downloadclient_id()
{
GivenFailedDownloadClientHistory();
var historyGrabbed = Builder<History.History>.CreateListOfSize(1)
.Build()
.ToList();
historyGrabbed.First().Data.Add("downloadClient", "SabnzbdClient");
historyGrabbed.First().Data.Add("downloadClientId", _failed.First().Id);
GivenGrabbedHistory(historyGrabbed);
var historyFailed = Builder<History.History>.CreateListOfSize(1)
.Build()
.ToList();
historyFailed.First().Data.Add("downloadClient", "SabnzbdClient");
historyFailed.First().Data.Add("downloadClientId", null);
GivenFailedHistory(historyFailed);
Subject.Execute(new CheckForFailedDownloadCommand());
VerifyFailedDownloads();
}
[Test] [Test]
public void should_not_process_if_already_added_to_history_as_failed() public void should_not_process_if_already_added_to_history_as_failed()
{ {

View File

@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Download;
using NzbDrone.Core.HealthCheck.Checks;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.HealthCheck.Checks
{
[TestFixture]
public class DownloadClientCheckFixture : CoreTest<DownloadClientCheck>
{
[Test]
public void should_return_warning_when_download_client_has_not_been_configured()
{
Mocker.GetMock<IProvideDownloadClient>()
.Setup(s => s.GetDownloadClient())
.Returns((IDownloadClient)null);
Subject.Check().ShouldBeWarning();
}
[Test]
public void should_return_error_when_download_client_throws()
{
var downloadClient = Mocker.GetMock<IDownloadClient>();
downloadClient.Setup(s => s.GetQueue())
.Throws<Exception>();
Mocker.GetMock<IProvideDownloadClient>()
.Setup(s => s.GetDownloadClient())
.Returns(downloadClient.Object);
Subject.Check().ShouldBeError();
}
[Test]
public void should_return_null_when_download_client_returns()
{
var downloadClient = Mocker.GetMock<IDownloadClient>();
downloadClient.Setup(s => s.GetQueue())
.Returns(new List<QueueItem>());
Mocker.GetMock<IProvideDownloadClient>()
.Setup(s => s.GetDownloadClient())
.Returns(downloadClient.Object);
Subject.Check().Should().BeNull();
}
}
}

View File

@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Common.Disk;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.HealthCheck.Checks;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.HealthCheck.Checks
{
[TestFixture]
public class DroneFactoryCheckFixture : CoreTest<DroneFactoryCheck>
{
private const string DRONE_FACTORY_FOLDER = @"C:\Test\Unsorted";
private void GivenDroneFactoryFolder(bool exists = false)
{
Mocker.GetMock<IConfigService>()
.SetupGet(s => s.DownloadedEpisodesFolder)
.Returns(DRONE_FACTORY_FOLDER);
Mocker.GetMock<IDiskProvider>()
.Setup(s => s.FolderExists(DRONE_FACTORY_FOLDER))
.Returns(exists);
}
[Test]
public void should_return_warning_when_drone_factory_folder_is_not_configured()
{
Mocker.GetMock<IConfigService>()
.SetupGet(s => s.DownloadedEpisodesFolder)
.Returns("");
Subject.Check().ShouldBeWarning();
}
[Test]
public void should_return_error_when_drone_factory_folder_does_not_exist()
{
GivenDroneFactoryFolder();
Subject.Check().ShouldBeError();
}
[Test]
public void should_return_error_when_unable_to_write_to_drone_factory_folder()
{
GivenDroneFactoryFolder(true);
Mocker.GetMock<IDiskProvider>()
.Setup(s => s.WriteAllText(It.IsAny<String>(), It.IsAny<String>()))
.Throws<Exception>();
Subject.Check().ShouldBeError();
}
[Test]
public void should_return_null_when_no_issues_found()
{
GivenDroneFactoryFolder(true);
Subject.Check().Should().BeNull();
}
}
}

View File

@ -0,0 +1,18 @@
using FluentAssertions;
using NzbDrone.Core.HealthCheck;
namespace NzbDrone.Core.Test.HealthCheck.Checks
{
public static class HealthCheckFixtureExtensions
{
public static void ShouldBeWarning(this Core.HealthCheck.HealthCheck result)
{
result.Type.Should().Be(HealthCheckResultType.Warning);
}
public static void ShouldBeError(this Core.HealthCheck.HealthCheck result)
{
result.Type.Should().Be(HealthCheckResultType.Error);
}
}
}

View File

@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Download;
using NzbDrone.Core.HealthCheck.Checks;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Indexers.Wombles;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.HealthCheck.Checks
{
[TestFixture]
public class IndexerCheckFixture : CoreTest<IndexerCheck>
{
[Test]
public void should_return_error_when_not_indexers_are_enabled()
{
Mocker.GetMock<IIndexerFactory>()
.Setup(s => s.GetAvailableProviders())
.Returns(new List<IIndexer>());
Subject.Check().ShouldBeError();
}
[Test]
public void should_return_warning_when_only_enabled_indexer_is_wombles()
{
var indexer = Mocker.GetMock<IIndexer>();
indexer.SetupGet(s => s.SupportsSearching).Returns(false);
Mocker.GetMock<IIndexerFactory>()
.Setup(s => s.GetAvailableProviders())
.Returns(new List<IIndexer>{indexer.Object});
Subject.Check().ShouldBeWarning();
}
[Test]
public void should_return_null_when_multiple_indexers_are_enabled()
{
var indexer1 = Mocker.GetMock<IIndexer>();
indexer1.SetupGet(s => s.SupportsSearching).Returns(true);
var indexer2 = Mocker.GetMock<Wombles>();
indexer2.SetupGet(s => s.SupportsSearching).Returns(false);
Mocker.GetMock<IIndexerFactory>()
.Setup(s => s.GetAvailableProviders())
.Returns(new List<IIndexer> { indexer1.Object, indexer2.Object });
Subject.Check().Should().BeNull();
}
[Test]
public void should_return_null_when_indexer_supports_searching()
{
var indexer1 = Mocker.GetMock<IIndexer>();
indexer1.SetupGet(s => s.SupportsSearching).Returns(true);
Mocker.GetMock<IIndexerFactory>()
.Setup(s => s.GetAvailableProviders())
.Returns(new List<IIndexer> { indexer1.Object });
Subject.Check().Should().BeNull();
}
}
}

View File

@ -0,0 +1,30 @@
using System;
using Moq;
using NUnit.Framework;
using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Core.HealthCheck.Checks;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.HealthCheck.Checks
{
[TestFixture]
public class UpdateCheckFixture : CoreTest<UpdateCheck>
{
[Test]
public void should_return_error_when_app_folder_is_write_protected()
{
WindowsOnly();
Mocker.GetMock<IAppFolderInfo>()
.Setup(s => s.StartUpFolder)
.Returns(@"C:\NzbDrone");
Mocker.GetMock<IDiskProvider>()
.Setup(s => s.WriteAllText(It.IsAny<String>(), It.IsAny<String>()))
.Throws<Exception>();
Subject.Check().ShouldBeError();
}
}
}

View File

@ -5,6 +5,7 @@ using NLog;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Common.Instrumentation; using NzbDrone.Common.Instrumentation;
using NzbDrone.Core.Datastore; using NzbDrone.Core.Datastore;
using NzbDrone.Core.Datastore.Migration.Framework;
using NzbDrone.Core.MediaFiles; using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Instrumentation; using NzbDrone.Core.Instrumentation;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;

View File

@ -2,7 +2,7 @@
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion> <ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{193ADD3B-792B-4173-8E4C-5A3F8F0237F0}</ProjectGuid> <ProjectGuid>{193ADD3B-792B-4173-8E4C-5A3F8F0237F0}</ProjectGuid>
@ -23,6 +23,8 @@
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
<Optimize>false</Optimize>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath> <OutputPath>bin\x86\Release\</OutputPath>
@ -32,6 +34,7 @@
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent> <RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
@ -40,72 +43,63 @@
<Reference Include="AutoMoq"> <Reference Include="AutoMoq">
<HintPath>..\packages\AutoMoq.1.6.1\lib\AutoMoq.dll</HintPath> <HintPath>..\packages\AutoMoq.1.6.1\lib\AutoMoq.dll</HintPath>
</Reference> </Reference>
<Reference Include="FizzWare.NBuilder, Version=3.0.1.0, Culture=neutral, PublicKeyToken=5651b03e12e42c12, processorArchitecture=MSIL">
<HintPath>..\packages\NBuilder.3.0.1.1\lib\FizzWare.NBuilder.dll</HintPath>
</Reference>
<Reference Include="FluentAssertions, Version=2.1.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\FluentAssertions.2.1.0.0\lib\net40\FluentAssertions.dll</HintPath>
</Reference>
<Reference Include="FluentMigrator, Version=1.1.1.0, Culture=neutral, PublicKeyToken=aacfc7de5acabf05, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\FluentMigrator.1.1.1.0\lib\40\FluentMigrator.dll</HintPath>
</Reference>
<Reference Include="FluentMigrator.Runner, Version=1.1.0.0, Culture=neutral, PublicKeyToken=aacfc7de5acabf05, processorArchitecture=x86">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\FluentMigrator.1.1.1.0\tools\FluentMigrator.Runner.dll</HintPath>
</Reference>
<Reference Include="FluentValidation, Version=5.0.0.1, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\FluentValidation.5.0.0.1\lib\Net40\FluentValidation.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.Practices.ServiceLocation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\CommonServiceLocator.1.0\lib\NET35\Microsoft.Practices.ServiceLocation.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Practices.Unity, Version=2.1.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Unity.2.1.505.2\lib\NET35\Microsoft.Practices.Unity.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Practices.Unity.Configuration"> <Reference Include="Microsoft.Practices.Unity.Configuration">
<HintPath>..\packages\Unity.2.1.505.2\lib\NET35\Microsoft.Practices.Unity.Configuration.dll</HintPath> <HintPath>..\packages\Unity.2.1.505.2\lib\NET35\Microsoft.Practices.Unity.Configuration.dll</HintPath>
</Reference> </Reference>
<Reference Include="Moq, Version=4.0.10827.0, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
<HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
</Reference>
<Reference Include="NCrunch.Framework, Version=1.46.0.9, Culture=neutral, PublicKeyToken=01d101bf6f3e0aea, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\NCrunch.Framework.1.46.0.9\lib\net35\NCrunch.Framework.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NLog, Version=2.1.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
</Reference>
<Reference Include="nunit.framework, Version=2.6.2.12296, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\NUnit.2.6.2\lib\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="Prowlin, Version=0.9.4456.26422, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Prowlin.0.9.4456.26422\lib\net40\Prowlin.dll</HintPath>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
<Reference Include="FizzWare.NBuilder, Version=3.0.1.0, Culture=neutral, PublicKeyToken=5651b03e12e42c12">
<HintPath>..\packages\NBuilder.3.0.1.1\lib\FizzWare.NBuilder.dll</HintPath>
</Reference>
<Reference Include="FluentAssertions">
<HintPath>..\packages\FluentAssertions.2.1.0.0\lib\net40\FluentAssertions.dll</HintPath>
</Reference>
<Reference Include="FluentMigrator">
<HintPath>..\packages\FluentMigrator.1.1.1.0\lib\40\FluentMigrator.dll</HintPath>
</Reference>
<Reference Include="FluentMigrator.Runner">
<HintPath>..\packages\FluentMigrator.1.1.1.0\tools\FluentMigrator.Runner.dll</HintPath>
</Reference>
<Reference Include="FluentValidation">
<HintPath>..\packages\FluentValidation.5.0.0.1\lib\Net40\FluentValidation.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Practices.ServiceLocation">
<HintPath>..\packages\CommonServiceLocator.1.0\lib\NET35\Microsoft.Practices.ServiceLocation.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Practices.Unity">
<HintPath>..\packages\Unity.2.1.505.2\lib\NET35\Microsoft.Practices.Unity.dll</HintPath>
</Reference>
<Reference Include="Moq, Version=4.0.10827.0, Culture=neutral, PublicKeyToken=69f491c39445e920">
<HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
</Reference>
<Reference Include="NCrunch.Framework">
<HintPath>..\packages\NCrunch.Framework.1.46.0.9\lib\net35\NCrunch.Framework.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\net40\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NLog">
<HintPath>..\packages\NLog.2.1.0\lib\net40\NLog.dll</HintPath>
</Reference>
<Reference Include="nunit.framework">
<HintPath>..\packages\NUnit.2.6.2\lib\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="Prowlin">
<HintPath>..\packages\Prowlin.0.9.4456.26422\lib\net40\Prowlin.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Blacklisting\BlacklistServiceFixture.cs" /> <Compile Include="Blacklisting\BlacklistServiceFixture.cs" />
<Compile Include="Blacklisting\BlacklistRepositoryFixture.cs" /> <Compile Include="Blacklisting\BlacklistRepositoryFixture.cs" />
<Compile Include="DataAugmentationFixture\Scene\SceneMappingProxyFixture.cs" /> <Compile Include="DataAugmentationFixture\Scene\SceneMappingProxyFixture.cs" />
<Compile Include="DataAugmentationFixture\Scene\SceneMappingServiceFixture.cs" /> <Compile Include="DataAugmentationFixture\Scene\SceneMappingServiceFixture.cs" />
<Compile Include="Datastore\MarrDataLazyLoadingFixture.cs" />
<Compile Include="Datastore\BasicRepositoryFixture.cs" /> <Compile Include="Datastore\BasicRepositoryFixture.cs" />
<Compile Include="Datastore\Converters\ProviderSettingConverterFixture.cs" /> <Compile Include="Datastore\Converters\ProviderSettingConverterFixture.cs" />
<Compile Include="Datastore\DatabaseFixture.cs" />
<Compile Include="Datastore\DatabaseRelationshipFixture.cs" /> <Compile Include="Datastore\DatabaseRelationshipFixture.cs" />
<Compile Include="Datastore\MappingExtentionFixture.cs" /> <Compile Include="Datastore\MappingExtentionFixture.cs" />
<Compile Include="Datastore\ObjectDatabaseFixture.cs" /> <Compile Include="Datastore\ObjectDatabaseFixture.cs" />
@ -131,6 +125,11 @@
<Compile Include="Framework\CoreTest.cs" /> <Compile Include="Framework\CoreTest.cs" />
<Compile Include="Framework\DbTest.cs" /> <Compile Include="Framework\DbTest.cs" />
<Compile Include="Framework\NBuilderExtensions.cs" /> <Compile Include="Framework\NBuilderExtensions.cs" />
<Compile Include="HealthCheck\Checks\UpdateCheckFixture.cs" />
<Compile Include="HealthCheck\Checks\IndexerCheckFixture.cs" />
<Compile Include="HealthCheck\Checks\DroneFactoryCheckFixture.cs" />
<Compile Include="HealthCheck\Checks\DownloadClientCheckFixture.cs" />
<Compile Include="HealthCheck\Checks\HealthCheckFixtureExtentions.cs" />
<Compile Include="HistoryTests\HistoryServiceFixture.cs" /> <Compile Include="HistoryTests\HistoryServiceFixture.cs" />
<Compile Include="Housekeeping\Housekeepers\CleanupOrphanedHistoryItemsFixture.cs" /> <Compile Include="Housekeeping\Housekeepers\CleanupOrphanedHistoryItemsFixture.cs" />
<Compile Include="Housekeeping\Housekeepers\CleanupOrphanedEpisodeFilesFixture.cs" /> <Compile Include="Housekeeping\Housekeepers\CleanupOrphanedEpisodeFilesFixture.cs" />
@ -211,6 +210,8 @@
<Compile Include="Housekeeping\Housekeepers\CleanupOrphanedEpisodesFixture.cs" /> <Compile Include="Housekeeping\Housekeepers\CleanupOrphanedEpisodesFixture.cs" />
<Compile Include="ThingiProviderTests\NullConfigFixture.cs" /> <Compile Include="ThingiProviderTests\NullConfigFixture.cs" />
<Compile Include="ThingiProvider\ProviderBaseFixture.cs" /> <Compile Include="ThingiProvider\ProviderBaseFixture.cs" />
<Compile Include="TvTests\EpisodeRepositoryTests\EpisodesWithFilesFixture.cs" />
<Compile Include="TvTests\EpisodeRepositoryTests\EpisodesWhereCutoffUnmetFixture.cs" />
<Compile Include="TvTests\RefreshEpisodeServiceFixture.cs" /> <Compile Include="TvTests\RefreshEpisodeServiceFixture.cs" />
<Compile Include="TvTests\EpisodeProviderTests\HandleEpisodeFileDeletedFixture.cs" /> <Compile Include="TvTests\EpisodeProviderTests\HandleEpisodeFileDeletedFixture.cs" />
<Compile Include="TvTests\EpisodeRepositoryTests\FindEpisodeFixture.cs" /> <Compile Include="TvTests\EpisodeRepositoryTests\FindEpisodeFixture.cs" />
@ -254,7 +255,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Marr.Data\Marr.Data.csproj"> <ProjectReference Include="..\Marr.Data\Marr.Data.csproj">
<Project>{f6fc6be7-0847-4817-a1ed-223dc647c3d7}</Project> <Project>{F6FC6BE7-0847-4817-A1ED-223DC647C3D7}</Project>
<Name>Marr.Data</Name> <Name>Marr.Data</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\NzbDrone.Common\NzbDrone.Common.csproj"> <ProjectReference Include="..\NzbDrone.Common\NzbDrone.Common.csproj">

View File

@ -36,7 +36,7 @@ namespace NzbDrone.Core.Test.ParserTests
[TestCase("Salamander.S01E01.FLEMISH.HDTV.x264-BRiGAND", Language.Flemish)] [TestCase("Salamander.S01E01.FLEMISH.HDTV.x264-BRiGAND", Language.Flemish)]
[TestCase("H.Polukatoikia.S03E13.Greek.PDTV.XviD-Ouzo", Language.Greek)] [TestCase("H.Polukatoikia.S03E13.Greek.PDTV.XviD-Ouzo", Language.Greek)]
[TestCase("Burn.Notice.S04E15.Brotherly.Love.GERMAN.DUBBED.WS.WEBRiP.XviD.REPACK-TVP", Language.German)] [TestCase("Burn.Notice.S04E15.Brotherly.Love.GERMAN.DUBBED.WS.WEBRiP.XviD.REPACK-TVP", Language.German)]
[TestCase("Ray Donovan - S01E01.720p.HDtv.x264-Evolve (NLsub)", Language.Norwegian)] [TestCase("Ray Donovan - S01E01.720p.HDtv.x264-Evolve (NLsub)", Language.Dutch)]
[TestCase("Shield,.The.1x13.Tueurs.De.Flics.FR.DVDRip.XviD", Language.French)] [TestCase("Shield,.The.1x13.Tueurs.De.Flics.FR.DVDRip.XviD", Language.French)]
[TestCase("True.Detective.S01E01.1080p.WEB-DL.Rus.Eng.TVKlondike", Language.Russian)] [TestCase("True.Detective.S01E01.1080p.WEB-DL.Rus.Eng.TVKlondike", Language.Russian)]
public void should_parse_language(string postTitle, Language language) public void should_parse_language(string postTitle, Language language)

View File

@ -130,7 +130,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
Subject.Map(_parsedEpisodeInfo, _series.TvRageId); Subject.Map(_parsedEpisodeInfo, _series.TvRageId);
Mocker.GetMock<IEpisodeService>() Mocker.GetMock<IEpisodeService>()
.Verify(v => v.FindEpisode(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>(), true), Times.Once()); .Verify(v => v.FindEpisodesBySceneNumbering(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()), Times.Once());
} }
[Test] [Test]
@ -141,7 +141,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
Subject.Map(_parsedEpisodeInfo, _series.TvRageId, _singleEpisodeSearchCriteria); Subject.Map(_parsedEpisodeInfo, _series.TvRageId, _singleEpisodeSearchCriteria);
Mocker.GetMock<IEpisodeService>() Mocker.GetMock<IEpisodeService>()
.Verify(v => v.FindEpisode(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>(), true), Times.Never()); .Verify(v => v.FindEpisodesBySceneNumbering(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()), Times.Never());
} }
[Test] [Test]
@ -153,7 +153,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
Subject.Map(_parsedEpisodeInfo, _series.TvRageId, _singleEpisodeSearchCriteria); Subject.Map(_parsedEpisodeInfo, _series.TvRageId, _singleEpisodeSearchCriteria);
Mocker.GetMock<IEpisodeService>() Mocker.GetMock<IEpisodeService>()
.Verify(v => v.FindEpisode(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>(), true), Times.Once()); .Verify(v => v.FindEpisodesBySceneNumbering(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()), Times.Once());
} }
[Test] [Test]
@ -162,7 +162,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
Subject.Map(_parsedEpisodeInfo, _series.TvRageId); Subject.Map(_parsedEpisodeInfo, _series.TvRageId);
Mocker.GetMock<IEpisodeService>() Mocker.GetMock<IEpisodeService>()
.Verify(v => v.FindEpisode(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>(), false), Times.Once()); .Verify(v => v.FindEpisode(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()), Times.Once());
} }
[Test] [Test]
@ -171,7 +171,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
Subject.Map(_parsedEpisodeInfo, _series.TvRageId, _singleEpisodeSearchCriteria); Subject.Map(_parsedEpisodeInfo, _series.TvRageId, _singleEpisodeSearchCriteria);
Mocker.GetMock<IEpisodeService>() Mocker.GetMock<IEpisodeService>()
.Verify(v => v.FindEpisode(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>(), false), Times.Never()); .Verify(v => v.FindEpisode(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()), Times.Never());
} }
[Test] [Test]
@ -182,7 +182,7 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
Subject.Map(_parsedEpisodeInfo, _series.TvRageId, _singleEpisodeSearchCriteria); Subject.Map(_parsedEpisodeInfo, _series.TvRageId, _singleEpisodeSearchCriteria);
Mocker.GetMock<IEpisodeService>() Mocker.GetMock<IEpisodeService>()
.Verify(v => v.FindEpisode(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>(), false), Times.Once()); .Verify(v => v.FindEpisode(It.IsAny<Int32>(), It.IsAny<Int32>(), It.IsAny<Int32>()), Times.Once());
} }
} }
} }

View File

@ -0,0 +1,167 @@
using System;
using System.Collections.Generic;
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.MediaFiles;
namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
{
[TestFixture]
public class EpisodesWhereCutoffUnmetFixture : DbTest<EpisodeRepository, Episode>
{
private Series _monitoredSeries;
private Series _unmonitoredSeries;
private PagingSpec<Episode> _pagingSpec;
private List<QualitiesBelowCutoff> _qualitiesBelowCutoff;
[SetUp]
public void Setup()
{
var qualityProfile = new QualityProfile
{
Id = 1,
Cutoff = Quality.WEBDL480p,
Items = new List<QualityProfileItem>
{
new QualityProfileItem { Allowed = true, Quality = Quality.SDTV },
new QualityProfileItem { Allowed = true, Quality = Quality.WEBDL480p },
new QualityProfileItem { Allowed = true, Quality = Quality.RAWHD }
}
};
_monitoredSeries = Builder<Series>.CreateNew()
.With(s => s.TvRageId = RandomNumber)
.With(s => s.Runtime = 30)
.With(s => s.Monitored = true)
.With(s => s.TitleSlug = "Title3")
.With(s => s.Id = qualityProfile.Id)
.BuildNew();
_unmonitoredSeries = Builder<Series>.CreateNew()
.With(s => s.TvdbId = RandomNumber)
.With(s => s.Runtime = 30)
.With(s => s.Monitored = false)
.With(s => s.TitleSlug = "Title2")
.With(s => s.Id = qualityProfile.Id)
.BuildNew();
_monitoredSeries.Id = Db.Insert(_monitoredSeries).Id;
_unmonitoredSeries.Id = Db.Insert(_unmonitoredSeries).Id;
_pagingSpec = new PagingSpec<Episode>
{
Page = 1,
PageSize = 10,
SortKey = "AirDate",
SortDirection = SortDirection.Ascending
};
_qualitiesBelowCutoff = new List<QualitiesBelowCutoff>
{
new QualitiesBelowCutoff(qualityProfile.Id, new[] {Quality.SDTV.Id})
};
var qualityMet = new EpisodeFile { Path = "a", Quality = new QualityModel { Quality = Quality.WEBDL480p } };
var qualityUnmet = new EpisodeFile { Path = "b", Quality = new QualityModel { Quality = Quality.SDTV } };
var qualityRawHD = new EpisodeFile { Path = "c", Quality = new QualityModel { Quality = Quality.RAWHD } };
MediaFileRepository fileRepository = Mocker.Resolve<MediaFileRepository>();
qualityMet = fileRepository.Insert(qualityMet);
qualityUnmet = fileRepository.Insert(qualityUnmet);
qualityRawHD = fileRepository.Insert(qualityRawHD);
var monitoredSeriesEpisodes = Builder<Episode>.CreateListOfSize(4)
.All()
.With(e => e.Id = 0)
.With(e => e.SeriesId = _monitoredSeries.Id)
.With(e => e.AirDateUtc = DateTime.Now.AddDays(-5))
.With(e => e.Monitored = true)
.With(e => e.EpisodeFileId = qualityUnmet.Id)
.TheFirst(1)
.With(e => e.Monitored = false)
.With(e => e.EpisodeFileId = qualityMet.Id)
.TheNext(1)
.With(e => e.EpisodeFileId = qualityRawHD.Id)
.TheLast(1)
.With(e => e.SeasonNumber = 0)
.Build();
var unmonitoredSeriesEpisodes = Builder<Episode>.CreateListOfSize(3)
.All()
.With(e => e.Id = 0)
.With(e => e.SeriesId = _unmonitoredSeries.Id)
.With(e => e.AirDateUtc = DateTime.Now.AddDays(-5))
.With(e => e.Monitored = true)
.With(e => e.EpisodeFileId = qualityUnmet.Id)
.TheFirst(1)
.With(e => e.Monitored = false)
.With(e => e.EpisodeFileId = qualityMet.Id)
.TheLast(1)
.With(e => e.SeasonNumber = 0)
.Build();
var unairedEpisodes = Builder<Episode>.CreateListOfSize(1)
.All()
.With(e => e.Id = 0)
.With(e => e.SeriesId = _monitoredSeries.Id)
.With(e => e.AirDateUtc = DateTime.Now.AddDays(5))
.With(e => e.Monitored = true)
.With(e => e.EpisodeFileId = qualityUnmet.Id)
.Build();
Db.InsertMany(monitoredSeriesEpisodes);
Db.InsertMany(unmonitoredSeriesEpisodes);
Db.InsertMany(unairedEpisodes);
}
private void GivenMonitoredFilterExpression()
{
_pagingSpec.FilterExpression = e => e.Monitored == true && e.Series.Monitored == true;
}
private void GivenUnmonitoredFilterExpression()
{
_pagingSpec.FilterExpression = e => e.Monitored == false || e.Series.Monitored == false;
}
[Test]
public void should_include_episodes_where_cutoff_has_not_be_met()
{
GivenMonitoredFilterExpression();
var spec = Subject.EpisodesWhereCutoffUnmet(_pagingSpec, _qualitiesBelowCutoff, false);
spec.Records.Should().HaveCount(1);
spec.Records.Should().OnlyContain(e => e.EpisodeFile.Value.Quality.Quality == Quality.SDTV);
}
[Test]
public void should_only_contain_monitored_episodes()
{
GivenMonitoredFilterExpression();
var spec = Subject.EpisodesWhereCutoffUnmet(_pagingSpec, _qualitiesBelowCutoff, false);
spec.Records.Should().HaveCount(1);
spec.Records.Should().OnlyContain(e => e.Monitored);
}
[Test]
public void should_only_contain_episode_with_monitored_series()
{
GivenMonitoredFilterExpression();
var spec = Subject.EpisodesWhereCutoffUnmet(_pagingSpec, _qualitiesBelowCutoff, false);
spec.Records.Should().HaveCount(1);
spec.Records.Should().OnlyContain(e => e.Series.Monitored);
}
}
}

View File

@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
{
[TestFixture]
public class EpisodesWithFilesFixture : DbTest<EpisodeRepository, Episode>
{
private const int SERIES_ID = 1;
private List<Episode> _episodes;
private List<EpisodeFile> _episodeFiles;
[SetUp]
public void Setup()
{
_episodeFiles = Builder<EpisodeFile>.CreateListOfSize(5)
.BuildListOfNew()
.ToList();
Db.InsertMany(_episodeFiles);
_episodes = Builder<Episode>.CreateListOfSize(10)
.All()
.With(e => e.EpisodeFileId = 0)
.With(e => e.SeriesId = SERIES_ID)
.BuildListOfNew()
.ToList();
for (int i = 0; i < _episodeFiles.Count; i++)
{
_episodes[i].EpisodeFileId = _episodeFiles[i].Id;
}
Db.InsertMany(_episodes);
}
[Test]
public void should_only_get_files_that_have_episode_files()
{
var result = Subject.EpisodesWithFiles(SERIES_ID);
result.Should().OnlyContain(e => e.EpisodeFileId > 0);
result.Should().HaveCount(_episodeFiles.Count);
}
[Test]
public void should_only_contain_episodes_for_the_given_series()
{
var episodeFile = Builder<EpisodeFile>.CreateNew()
.With(f => f.Path = "another path")
.BuildNew();
Db.Insert(episodeFile);
var episode = Builder<Episode>.CreateNew()
.With(e => e.SeriesId = SERIES_ID + 10)
.With(e => e.EpisodeFileId = episodeFile.Id)
.BuildNew();
Db.Insert(episode);
Subject.EpisodesWithFiles(episode.SeriesId).Should().OnlyContain(e => e.SeriesId == episode.SeriesId);
}
[Test]
public void should_have_episode_file_loaded()
{
Subject.EpisodesWithFiles(SERIES_ID).Should().OnlyContain(e => e.EpisodeFile.IsLoaded);
}
}
}

View File

@ -72,13 +72,36 @@ namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
.Build(); .Build();
var unairedEpisodes = Builder<Episode>.CreateListOfSize(1)
.All()
.With(e => e.Id = 0)
.With(e => e.SeriesId = _monitoredSeries.Id)
.With(e => e.EpisodeFileId = 0)
.With(e => e.AirDateUtc = DateTime.Now.AddDays(5))
.With(e => e.Monitored = true)
.Build();
Db.InsertMany(monitoredSeriesEpisodes); Db.InsertMany(monitoredSeriesEpisodes);
Db.InsertMany(unmonitoredSeriesEpisodes); Db.InsertMany(unmonitoredSeriesEpisodes);
Db.InsertMany(unairedEpisodes);
}
private void GivenMonitoredFilterExpression()
{
_pagingSpec.FilterExpression = e => e.Monitored == true && e.Series.Monitored == true;
}
private void GivenUnmonitoredFilterExpression()
{
_pagingSpec.FilterExpression = e => e.Monitored == false || e.Series.Monitored == false;
} }
[Test] [Test]
public void should_get_monitored_episodes() public void should_get_monitored_episodes()
{ {
GivenMonitoredFilterExpression();
var episodes = Subject.EpisodesWithoutFiles(_pagingSpec, false); var episodes = Subject.EpisodesWithoutFiles(_pagingSpec, false);
episodes.Records.Should().HaveCount(1); episodes.Records.Should().HaveCount(1);
@ -96,6 +119,8 @@ namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
[Test] [Test]
public void should_not_include_unmonitored_episodes() public void should_not_include_unmonitored_episodes()
{ {
GivenMonitoredFilterExpression();
var episodes = Subject.EpisodesWithoutFiles(_pagingSpec, false); var episodes = Subject.EpisodesWithoutFiles(_pagingSpec, false);
episodes.Records.Should().NotContain(e => e.Monitored == false); episodes.Records.Should().NotContain(e => e.Monitored == false);
@ -104,17 +129,19 @@ namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
[Test] [Test]
public void should_not_contain_unmonitored_series() public void should_not_contain_unmonitored_series()
{ {
GivenMonitoredFilterExpression();
var episodes = Subject.EpisodesWithoutFiles(_pagingSpec, false); var episodes = Subject.EpisodesWithoutFiles(_pagingSpec, false);
episodes.Records.Should().NotContain(e => e.SeriesId == _unmonitoredSeries.Id); episodes.Records.Should().NotContain(e => e.SeriesId == _unmonitoredSeries.Id);
} }
[Test] [Test]
public void should_have_count_of_one() public void should_not_return_unaired()
{ {
var episodes = Subject.EpisodesWithoutFiles(_pagingSpec, false); var episodes = Subject.EpisodesWithoutFiles(_pagingSpec, false);
episodes.TotalRecords.Should().Be(1); episodes.TotalRecords.Should().Be(4);
} }
} }
} }

View File

@ -1,4 +1,5 @@
using FizzWare.NBuilder; using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions; using FluentAssertions;
using NUnit.Framework; using NUnit.Framework;
using NzbDrone.Core.Test.Framework; using NzbDrone.Core.Test.Framework;
@ -9,46 +10,55 @@ namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
[TestFixture] [TestFixture]
public class FindEpisodeFixture : DbTest<EpisodeRepository, Episode> public class FindEpisodeFixture : DbTest<EpisodeRepository, Episode>
{ {
private Episode _episode; private Episode _episode1;
private Episode _episode2;
[SetUp] [SetUp]
public void Setup() public void Setup()
{ {
_episode = Builder<Episode>.CreateNew() _episode1 = Builder<Episode>.CreateNew()
.With(e => e.Id = 0) .With(e => e.SeriesId = 1)
.With(e => e.SeriesId = 1) .With(e => e.SeasonNumber = 1)
.With(e => e.SeasonNumber = 1) .With(e => e.SceneSeasonNumber = 2)
.With(e => e.SceneSeasonNumber = 2) .With(e => e.EpisodeNumber = 3)
.With(e => e.EpisodeNumber = 3) .With(e => e.AbsoluteEpisodeNumber = 3)
.With(e => e.AbsoluteEpisodeNumber = 3) .With(e => e.SceneEpisodeNumber = 4)
.With(e => e.SceneEpisodeNumber = 4) .BuildNew();
.Build();
_episode = Db.Insert(_episode); _episode2 = Builder<Episode>.CreateNew()
.With(e => e.SeriesId = 1)
.With(e => e.SeasonNumber = 1)
.With(e => e.SceneSeasonNumber = 2)
.With(e => e.EpisodeNumber = 4)
.With(e => e.SceneEpisodeNumber = 4)
.BuildNew();
_episode1 = Db.Insert(_episode1);
} }
[Test] [Test]
public void should_find_episode_by_scene_numbering() public void should_find_episode_by_scene_numbering()
{ {
Subject.FindEpisodeBySceneNumbering(_episode.SeriesId, _episode.SceneSeasonNumber, _episode.SceneEpisodeNumber) Subject.FindEpisodesBySceneNumbering(_episode1.SeriesId, _episode1.SceneSeasonNumber, _episode1.SceneEpisodeNumber)
.First()
.Id .Id
.Should() .Should()
.Be(_episode.Id); .Be(_episode1.Id);
} }
[Test] [Test]
public void should_find_episode_by_standard_numbering() public void should_find_episode_by_standard_numbering()
{ {
Subject.Find(_episode.SeriesId, _episode.SeasonNumber, _episode.EpisodeNumber) Subject.Find(_episode1.SeriesId, _episode1.SeasonNumber, _episode1.EpisodeNumber)
.Id .Id
.Should() .Should()
.Be(_episode.Id); .Be(_episode1.Id);
} }
[Test] [Test]
public void should_not_find_episode_that_does_not_exist() public void should_not_find_episode_that_does_not_exist()
{ {
Subject.Find(_episode.SeriesId, _episode.SeasonNumber + 1, _episode.EpisodeNumber) Subject.Find(_episode1.SeriesId, _episode1.SeasonNumber + 1, _episode1.EpisodeNumber)
.Should() .Should()
.BeNull(); .BeNull();
} }
@ -56,10 +66,20 @@ namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
[Test] [Test]
public void should_find_episode_by_absolute_numbering() public void should_find_episode_by_absolute_numbering()
{ {
Subject.Find(_episode.SeriesId, _episode.AbsoluteEpisodeNumber.Value) Subject.Find(_episode1.SeriesId, _episode1.AbsoluteEpisodeNumber.Value)
.Id .Id
.Should() .Should()
.Be(_episode.Id); .Be(_episode1.Id);
}
[Test]
public void should_return_multiple_episode_if_multiple_match_by_scene_numbering()
{
_episode2 = Db.Insert(_episode2);
Subject.FindEpisodesBySceneNumbering(_episode1.SeriesId, _episode1.SceneSeasonNumber, _episode1.SceneEpisodeNumber)
.Should()
.HaveCount(2);
} }
} }
} }

View File

@ -19,7 +19,7 @@ namespace NzbDrone.Core.Test.UpdateTests
public void finds_update_when_version_lower() public void finds_update_when_version_lower()
{ {
UseRealHttp(); UseRealHttp();
Subject.GetLatestUpdate("master", new Version(1, 0)).Should().NotBeNull(); Subject.GetLatestUpdate("master", new Version(2, 0)).Should().NotBeNull();
} }
} }
} }

View File

@ -8,7 +8,7 @@ namespace NzbDrone.Core.Blacklisting
{ {
public interface IBlacklistRepository : IBasicRepository<Blacklist> public interface IBlacklistRepository : IBasicRepository<Blacklist>
{ {
bool Blacklisted(string sourceTitle); bool Blacklisted(int seriesId, string sourceTitle);
List<Blacklist> BlacklistedBySeries(int seriesId); List<Blacklist> BlacklistedBySeries(int seriesId);
} }
@ -19,9 +19,11 @@ namespace NzbDrone.Core.Blacklisting
{ {
} }
public bool Blacklisted(string sourceTitle) public bool Blacklisted(int seriesId, string sourceTitle)
{ {
return Query.Where(e => e.SourceTitle.Contains(sourceTitle)).Any(); return Query.Where(e => e.SeriesId == seriesId)
.AndWhere(e => e.SourceTitle.Contains(sourceTitle))
.Any();
} }
public List<Blacklist> BlacklistedBySeries(int seriesId) public List<Blacklist> BlacklistedBySeries(int seriesId)

View File

@ -9,7 +9,7 @@ namespace NzbDrone.Core.Blacklisting
{ {
public interface IBlacklistService public interface IBlacklistService
{ {
bool Blacklisted(string sourceTitle); bool Blacklisted(int seriesId,string sourceTitle);
PagingSpec<Blacklist> Paged(PagingSpec<Blacklist> pagingSpec); PagingSpec<Blacklist> Paged(PagingSpec<Blacklist> pagingSpec);
void Delete(int id); void Delete(int id);
} }
@ -25,9 +25,9 @@ namespace NzbDrone.Core.Blacklisting
_redownloadFailedDownloadService = redownloadFailedDownloadService; _redownloadFailedDownloadService = redownloadFailedDownloadService;
} }
public bool Blacklisted(string sourceTitle) public bool Blacklisted(int seriesId, string sourceTitle)
{ {
return _blacklistRepository.Blacklisted(sourceTitle); return _blacklistRepository.Blacklisted(seriesId,sourceTitle);
} }
public PagingSpec<Blacklist> Paged(PagingSpec<Blacklist> pagingSpec) public PagingSpec<Blacklist> Paged(PagingSpec<Blacklist> pagingSpec)

View File

@ -130,7 +130,7 @@ namespace NzbDrone.Core.Configuration
public string Branch public string Branch
{ {
get { return GetValue("Branch", "master"); } get { return GetValue("Branch", "master").ToLowerInvariant(); }
} }
public string Username public string Username

View File

@ -6,6 +6,7 @@ using Marr.Data;
using Marr.Data.QGen; using Marr.Data.QGen;
using NzbDrone.Core.Datastore.Events; using NzbDrone.Core.Datastore.Events;
using NzbDrone.Common; using NzbDrone.Common;
using NzbDrone.Core.Datastore.Extentions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
@ -26,7 +27,7 @@ namespace NzbDrone.Core.Datastore
void InsertMany(IList<TModel> model); void InsertMany(IList<TModel> model);
void UpdateMany(IList<TModel> model); void UpdateMany(IList<TModel> model);
void DeleteMany(List<TModel> model); void DeleteMany(List<TModel> model);
void Purge(); void Purge(bool vacuum = false);
bool HasItems(); bool HasItems();
void DeleteMany(IEnumerable<int> ids); void DeleteMany(IEnumerable<int> ids);
void SetFields(TModel model, params Expression<Func<TModel, object>>[] properties); void SetFields(TModel model, params Expression<Func<TModel, object>>[] properties);
@ -215,9 +216,18 @@ namespace NzbDrone.Core.Datastore
} }
} }
public void Purge() public void Purge(bool vacuum = false)
{ {
DataMapper.Delete<TModel>(c => c.Id > -1); DataMapper.Delete<TModel>(c => c.Id > -1);
if (vacuum)
{
Vacuum();
}
}
protected void Vacuum()
{
_database.Vacuum();
} }
public bool HasItems() public bool HasItems()
@ -257,11 +267,6 @@ namespace NzbDrone.Core.Datastore
.Take(pagingSpec.PageSize); .Take(pagingSpec.PageSize);
} }
public void DeleteAll()
{
DataMapper.Delete<TModel>(c => c.Id > 0);
}
protected void ModelCreated(TModel model) protected void ModelCreated(TModel model)
{ {
PublishModelEvent(model, ModelAction.Created); PublishModelEvent(model, ModelAction.Created);

View File

@ -1,25 +1,55 @@
using System; using System;
using Marr.Data; using Marr.Data;
using NLog;
using NzbDrone.Common.Instrumentation;
namespace NzbDrone.Core.Datastore namespace NzbDrone.Core.Datastore
{ {
public interface IDatabase public interface IDatabase
{ {
IDataMapper GetDataMapper(); IDataMapper GetDataMapper();
Version Version { get; }
void Vacuum();
} }
public class Database : IDatabase public class Database : IDatabase
{ {
private readonly Func<IDataMapper> _dataMapperFactory; private readonly Func<IDataMapper> _datamapperFactory;
public Database(Func<IDataMapper> dataMapperFactory) private Logger logger = NzbDroneLogger.GetLogger();
public Database(Func<IDataMapper> datamapperFactory)
{ {
_dataMapperFactory = dataMapperFactory; _datamapperFactory = datamapperFactory;
} }
public IDataMapper GetDataMapper() public IDataMapper GetDataMapper()
{ {
return _dataMapperFactory(); return _datamapperFactory();
}
public Version Version
{
get
{
var version = _datamapperFactory().ExecuteScalar("SELECT sqlite_version()").ToString();
return new Version(version);
}
}
public void Vacuum()
{
try
{
logger.Info("Vacuuming database");
_datamapperFactory().ExecuteNonQuery("Vacuum;");
logger.Info("Database Compressed");
}
catch (Exception e)
{
logger.Error("An Error occurred while vacuuming database.", e);
}
} }
} }
} }

View File

@ -29,17 +29,13 @@ namespace NzbDrone.Core.Datastore
public static void RegisterDatabase(IContainer container) public static void RegisterDatabase(IContainer container)
{ {
container.Resolve<IDbFactory>().Create(); var mainDb = container.Resolve<IDbFactory>().Create();
container.Register(c => c.Resolve<IDbFactory>().Create()); container.Register(mainDb);
container.Resolve<IDbFactory>().Create(MigrationType.Log); var logDb = container.Resolve<IDbFactory>().Create(MigrationType.Log);
container.Register<ILogRepository>(c => container.Register<ILogRepository>(c => new LogRepository(logDb, c.Resolve<IEventAggregator>()));
{
var db = c.Resolve<IDbFactory>().Create(MigrationType.Log);
return new LogRepository(db, c.Resolve<IEventAggregator>());
});
} }
public DbFactory(IMigrationController migrationController, IConnectionStringFactory connectionStringFactory) public DbFactory(IMigrationController migrationController, IConnectionStringFactory connectionStringFactory)
@ -73,7 +69,7 @@ namespace NzbDrone.Core.Datastore
_migrationController.MigrateToLatest(connectionString, migrationType); _migrationController.MigrateToLatest(connectionString, migrationType);
return new Database(() => var db = new Database(() =>
{ {
var dataMapper = new DataMapper(SQLiteFactory.Instance, connectionString) var dataMapper = new DataMapper(SQLiteFactory.Instance, connectionString)
{ {
@ -82,6 +78,11 @@ namespace NzbDrone.Core.Datastore
return dataMapper; return dataMapper;
}); });
db.Vacuum();
return db;
} }
} }
} }

View File

@ -4,7 +4,7 @@ using Marr.Data;
using Marr.Data.Mapping; using Marr.Data.Mapping;
using NzbDrone.Common.Reflection; using NzbDrone.Common.Reflection;
namespace NzbDrone.Core.Datastore namespace NzbDrone.Core.Datastore.Extentions
{ {
public static class MappingExtensions public static class MappingExtensions
{ {

View File

@ -2,7 +2,7 @@
using System.Linq; using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
namespace NzbDrone.Core.Datastore namespace NzbDrone.Core.Datastore.Extentions
{ {
public static class PagingSpecExtensions public static class PagingSpecExtensions
{ {

View File

@ -4,7 +4,7 @@ using System.Linq.Expressions;
using Marr.Data; using Marr.Data;
using Marr.Data.Mapping; using Marr.Data.Mapping;
namespace NzbDrone.Core.Datastore namespace NzbDrone.Core.Datastore.Extentions
{ {
public static class RelationshipExtensions public static class RelationshipExtensions
{ {

View File

@ -0,0 +1,26 @@
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(45)]
public class add_indexes : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Create.Index().OnTable("Blacklist").OnColumn("SeriesId");
Create.Index().OnTable("EpisodeFiles").OnColumn("SeriesId");
Create.Index().OnTable("Episodes").OnColumn("EpisodeFileId");
Create.Index().OnTable("Episodes").OnColumn("SeriesId");
Create.Index().OnTable("History").OnColumn("EpisodeId");
Create.Index().OnTable("History").OnColumn("Date");
Create.Index().OnTable("Series").OnColumn("Path");
Create.Index().OnTable("Series").OnColumn("CleanTitle");
Create.Index().OnTable("Series").OnColumn("TvRageId");
}
}
}

View File

@ -1,5 +1,4 @@
using System.Collections.Generic; using System.Reflection;
using System.Reflection;
using FluentMigrator.Runner; using FluentMigrator.Runner;
using FluentMigrator.Runner.Initialization; using FluentMigrator.Runner.Initialization;
using FluentMigrator.Runner.Processors.Sqlite; using FluentMigrator.Runner.Processors.Sqlite;
@ -17,8 +16,6 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
private readonly ISQLiteAlter _sqLiteAlter; private readonly ISQLiteAlter _sqLiteAlter;
private readonly ISqLiteMigrationHelper _migrationHelper; private readonly ISqLiteMigrationHelper _migrationHelper;
private static readonly HashSet<string> MigrationCache = new HashSet<string>();
public MigrationController(IAnnouncer announcer, ISQLiteAlter sqLiteAlter, ISqLiteMigrationHelper migrationHelper) public MigrationController(IAnnouncer announcer, ISQLiteAlter sqLiteAlter, ISqLiteMigrationHelper migrationHelper)
{ {
_announcer = announcer; _announcer = announcer;
@ -28,33 +25,26 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
public void MigrateToLatest(string connectionString, MigrationType migrationType) public void MigrateToLatest(string connectionString, MigrationType migrationType)
{ {
lock (MigrationCache) _announcer.Heading("Migrating " + connectionString);
{
if (MigrationCache.Contains(connectionString.ToLower())) return;
_announcer.Heading("Migrating " + connectionString); var assembly = Assembly.GetExecutingAssembly();
var assembly = Assembly.GetExecutingAssembly(); var migrationContext = new RunnerContext(_announcer)
{
Namespace = "NzbDrone.Core.Datastore.Migration",
ApplicationContext = new MigrationContext
{
MigrationType = migrationType,
SQLiteAlter = _sqLiteAlter,
MigrationHelper = _migrationHelper,
}
};
var migrationContext = new RunnerContext(_announcer) var options = new MigrationOptions { PreviewOnly = false, Timeout = 60 };
{ var factory = new SqliteProcessorFactory();
Namespace = "NzbDrone.Core.Datastore.Migration", var processor = factory.Create(connectionString, _announcer, options);
ApplicationContext = new MigrationContext var runner = new MigrationRunner(assembly, migrationContext, processor);
{ runner.MigrateUp(true);
MigrationType = migrationType,
SQLiteAlter = _sqLiteAlter,
MigrationHelper = _migrationHelper,
}
};
var options = new MigrationOptions { PreviewOnly = false, Timeout = 60 };
var factory = new SqliteProcessorFactory();
var processor = factory.Create(connectionString, _announcer, options);
var runner = new MigrationRunner(assembly, migrationContext, processor);
runner.MigrateUp(true);
MigrationCache.Add(connectionString.ToLower());
}
} }
} }
} }

View File

@ -1,4 +1,4 @@
namespace NzbDrone.Core.Datastore namespace NzbDrone.Core.Datastore.Migration.Framework
{ {
public enum MigrationType public enum MigrationType
{ {

View File

@ -7,6 +7,7 @@ using NzbDrone.Core.Blacklisting;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.DataAugmentation.Scene; using NzbDrone.Core.DataAugmentation.Scene;
using NzbDrone.Core.Datastore.Converters; using NzbDrone.Core.Datastore.Converters;
using NzbDrone.Core.Datastore.Extentions;
using NzbDrone.Core.Download; using NzbDrone.Core.Download;
using NzbDrone.Core.Indexers; using NzbDrone.Core.Indexers;
using NzbDrone.Core.Instrumentation; using NzbDrone.Core.Instrumentation;

View File

@ -35,7 +35,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
return true; return true;
} }
if (_blacklistService.Blacklisted(subject.Release.Title)) if (_blacklistService.Blacklisted(subject.Series.Id, subject.Release.Title))
{ {
_logger.Trace("{0} is blacklisted, rejecting.", subject.Release.Title); _logger.Trace("{0} is blacklisted, rejecting.", subject.Release.Title);
return false; return false;

View File

@ -69,14 +69,19 @@ namespace NzbDrone.Core.DiskSpace
try try
{ {
var freeSpace = _diskProvider.GetAvailableSpace(path).Value; var freeSpace = _diskProvider.GetAvailableSpace(path);
var totalSpace = _diskProvider.GetTotalSize(path).Value; var totalSpace = _diskProvider.GetTotalSize(path);
if (!freeSpace.HasValue || !totalSpace.HasValue)
{
continue;
}
diskSpace = new DiskSpace diskSpace = new DiskSpace
{ {
Path = path, Path = path,
FreeSpace = freeSpace, FreeSpace = freeSpace.Value,
TotalSpace = totalSpace TotalSpace = totalSpace.Value
}; };
diskSpace.Label = _diskProvider.GetVolumeLabel(path); diskSpace.Label = _diskProvider.GetVolumeLabel(path);

View File

@ -58,11 +58,21 @@ namespace NzbDrone.Core.Download.Clients.Blackhole
{ {
} }
public void Execute(TestBlackholeCommand message) public override void Test()
{ {
var testPath = Path.Combine(message.Folder, "drone_test.txt"); PerformTest(Settings.Folder);
}
private void PerformTest(string folder)
{
var testPath = Path.Combine(folder, "drone_test.txt");
_diskProvider.WriteAllText(testPath, DateTime.Now.ToString()); _diskProvider.WriteAllText(testPath, DateTime.Now.ToString());
_diskProvider.DeleteFile(testPath); _diskProvider.DeleteFile(testPath);
} }
public void Execute(TestBlackholeCommand message)
{
PerformTest(message.Folder);
}
} }
} }

View File

@ -0,0 +1,15 @@
using NzbDrone.Common.Exceptions;
namespace NzbDrone.Core.Download.Clients
{
public class DownloadClientException : NzbDroneException
{
public DownloadClientException(string message, params object[] args) : base(message, args)
{
}
public DownloadClientException(string message) : base(message)
{
}
}
}

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using NLog; using NLog;
using NzbDrone.Core.Messaging.Commands; using NzbDrone.Core.Messaging.Commands;
using NzbDrone.Core.Parser; using NzbDrone.Core.Parser;
@ -42,9 +43,21 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
public override IEnumerable<QueueItem> GetQueue() public override IEnumerable<QueueItem> GetQueue()
{ {
var items = _proxy.GetQueue(Settings); List<NzbgetQueueItem> queue;
foreach (var nzbGetQueueItem in items) try
{
queue = _proxy.GetQueue(Settings);
}
catch (DownloadClientException ex)
{
_logger.ErrorException(ex.Message, ex);
return Enumerable.Empty<QueueItem>();
}
var queueItems = new List<QueueItem>();
foreach (var nzbGetQueueItem in queue)
{ {
var queueItem = new QueueItem(); var queueItem = new QueueItem();
queueItem.Id = nzbGetQueueItem.NzbId.ToString(); queueItem.Id = nzbGetQueueItem.NzbId.ToString();
@ -60,9 +73,10 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
if (remoteEpisode.Series == null) continue; if (remoteEpisode.Series == null) continue;
queueItem.RemoteEpisode = remoteEpisode; queueItem.RemoteEpisode = remoteEpisode;
queueItems.Add(queueItem);
yield return queueItem;
} }
return queueItems;
} }
public override IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 10) public override IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 10)
@ -80,7 +94,12 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
throw new NotImplementedException(); throw new NotImplementedException();
} }
public VersionResponse GetVersion(string host = null, int port = 0, string username = null, string password = null) public override void Test()
{
_proxy.GetVersion(Settings);
}
private VersionResponse GetVersion(string host = null, int port = 0, string username = null, string password = null)
{ {
return _proxy.GetVersion(Settings); return _proxy.GetVersion(Settings);
} }

View File

@ -57,7 +57,10 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
private IRestClient BuildClient(NzbgetSettings settings) private IRestClient BuildClient(NzbgetSettings settings)
{ {
var url = String.Format("http://{0}:{1}/jsonrpc", var protocol = settings.UseSsl ? "https" : "http";
var url = String.Format("{0}://{1}:{2}/jsonrpc",
protocol,
settings.Host, settings.Host,
settings.Port); settings.Port);
@ -82,13 +85,13 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
{ {
if (response.ResponseStatus != ResponseStatus.Completed) if (response.ResponseStatus != ResponseStatus.Completed)
{ {
throw new ApplicationException("Unable to connect to NzbGet, please check your settings"); throw new DownloadClientException("Unable to connect to NzbGet, please check your settings");
} }
var result = Json.Deserialize<JsonError>(response.Content); var result = Json.Deserialize<JsonError>(response.Content);
if (result.Error != null) if (result.Error != null)
throw new ApplicationException(result.Error.ToString()); throw new DownloadClientException("Error response received from nzbget: {0}", result.Error.ToString());
} }
} }
} }

View File

@ -12,8 +12,8 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
{ {
RuleFor(c => c.Host).NotEmpty(); RuleFor(c => c.Host).NotEmpty();
RuleFor(c => c.Port).GreaterThan(0); RuleFor(c => c.Port).GreaterThan(0);
RuleFor(c => c.Username).NotEmpty(); RuleFor(c => c.Username).NotEmpty().When(c => !String.IsNullOrWhiteSpace(c.Password));
RuleFor(c => c.Password).NotEmpty(); RuleFor(c => c.Password).NotEmpty().When(c => !String.IsNullOrWhiteSpace(c.Username));
} }
} }
@ -45,12 +45,15 @@ namespace NzbDrone.Core.Download.Clients.Nzbget
[FieldDefinition(4, Label = "Category", Type = FieldType.Textbox)] [FieldDefinition(4, Label = "Category", Type = FieldType.Textbox)]
public String TvCategory { get; set; } public String TvCategory { get; set; }
[FieldDefinition(5, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(NzbgetPriority))] [FieldDefinition(5, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(NzbgetPriority), HelpText = "Priority to use when grabbing episodes that aired within the last 14 days")]
public Int32 RecentTvPriority { get; set; } public Int32 RecentTvPriority { get; set; }
[FieldDefinition(6, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(NzbgetPriority))] [FieldDefinition(6, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(NzbgetPriority), HelpText = "Priority to use when grabbing episodes that aired over 14 days ago")]
public Int32 OlderTvPriority { get; set; } public Int32 OlderTvPriority { get; set; }
[FieldDefinition(7, Label = "Use SSL", Type = FieldType.Checkbox)]
public Boolean UseSsl { get; set; }
public ValidationResult Validate() public ValidationResult Validate()
{ {
return Validator.Validate(this); return Validator.Validate(this);

View File

@ -80,11 +80,21 @@ namespace NzbDrone.Core.Download.Clients.Pneumatic
{ {
} }
public void Execute(TestPneumaticCommand message) public override void Test()
{ {
var testPath = Path.Combine(message.Folder, "drone_test.txt"); PerformTest(Settings.Folder);
}
private void PerformTest(string folder)
{
var testPath = Path.Combine(folder, "drone_test.txt");
_diskProvider.WriteAllText(testPath, DateTime.Now.ToString()); _diskProvider.WriteAllText(testPath, DateTime.Now.ToString());
_diskProvider.DeleteFile(testPath); _diskProvider.DeleteFile(testPath);
} }
public void Execute(TestPneumaticCommand message)
{
PerformTest(message.Folder);
}
} }
} }

View File

@ -60,11 +60,21 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
{ {
return _queueCache.Get("queue", () => return _queueCache.Get("queue", () =>
{ {
var sabQueue = _sabnzbdProxy.GetQueue(0, 0, Settings).Items; SabnzbdQueue sabQueue;
try
{
sabQueue = _sabnzbdProxy.GetQueue(0, 0, Settings);
}
catch (DownloadClientException ex)
{
_logger.ErrorException(ex.Message, ex);
return Enumerable.Empty<QueueItem>();
}
var queueItems = new List<QueueItem>(); var queueItems = new List<QueueItem>();
foreach (var sabQueueItem in sabQueue) foreach (var sabQueueItem in sabQueue.Items)
{ {
var queueItem = new QueueItem(); var queueItem = new QueueItem();
queueItem.Id = sabQueueItem.Id; queueItem.Id = sabQueueItem.Id;
@ -91,10 +101,21 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
public override IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 10) public override IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 10)
{ {
var items = _sabnzbdProxy.GetHistory(start, limit, Settings).Items; SabnzbdHistory sabHistory;
try
{
sabHistory = _sabnzbdProxy.GetHistory(start, limit, Settings);
}
catch (DownloadClientException ex)
{
_logger.ErrorException(ex.Message, ex);
return Enumerable.Empty<HistoryItem>();
}
var historyItems = new List<HistoryItem>(); var historyItems = new List<HistoryItem>();
foreach (var sabHistoryItem in items) foreach (var sabHistoryItem in sabHistory.Items)
{ {
var historyItem = new HistoryItem(); var historyItem = new HistoryItem();
historyItem.Id = sabHistoryItem.Id; historyItem.Id = sabHistoryItem.Id;
@ -122,6 +143,11 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
_sabnzbdProxy.RemoveFrom("history", id, Settings); _sabnzbdProxy.RemoveFrom("history", id, Settings);
} }
public override void Test()
{
_sabnzbdProxy.GetCategories(Settings);
}
public void Execute(TestSabnzbdCommand message) public void Execute(TestSabnzbdCommand message)
{ {
var settings = new SabnzbdSettings(); var settings = new SabnzbdSettings();

View File

@ -2,6 +2,7 @@
using System.IO; using System.IO;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using NLog; using NLog;
using NzbDrone.Common;
using NzbDrone.Common.Serializer; using NzbDrone.Common.Serializer;
using NzbDrone.Core.Download.Clients.Sabnzbd.Responses; using NzbDrone.Core.Download.Clients.Sabnzbd.Responses;
using RestSharp; using RestSharp;
@ -97,7 +98,6 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
var response = ProcessRequest(request, action, settings); var response = ProcessRequest(request, action, settings);
return Json.Deserialize<SabnzbdQueue>(JObject.Parse(response).SelectToken("queue").ToString()); return Json.Deserialize<SabnzbdQueue>(JObject.Parse(response).SelectToken("queue").ToString());
} }
public SabnzbdHistory GetHistory(int start, int limit, SabnzbdSettings settings) public SabnzbdHistory GetHistory(int start, int limit, SabnzbdSettings settings)
@ -113,14 +113,16 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
{ {
var protocol = settings.UseSsl ? "https" : "http"; var protocol = settings.UseSsl ? "https" : "http";
var url = string.Format(@"{0}://{1}:{2}/api?{3}&apikey={4}&ma_username={5}&ma_password={6}&output=json", var authentication = settings.ApiKey.IsNullOrWhiteSpace() ?
String.Format("ma_username={0}&ma_password={1}", settings.Username, settings.Password) :
String.Format("apikey={0}", settings.ApiKey);
var url = string.Format(@"{0}://{1}:{2}/api?{3}&{4}&output=json",
protocol, protocol,
settings.Host, settings.Host,
settings.Port, settings.Port,
action, action,
settings.ApiKey, authentication);
settings.Username,
settings.Password);
_logger.Trace(url); _logger.Trace(url);
@ -131,7 +133,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
{ {
if (response.ResponseStatus != ResponseStatus.Completed) if (response.ResponseStatus != ResponseStatus.Completed)
{ {
throw new ApplicationException("Unable to connect to SABnzbd, please check your settings"); throw new DownloadClientException("Unable to connect to SABnzbd, please check your settings");
} }
SabnzbdJsonError result; SabnzbdJsonError result;
@ -156,7 +158,7 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
} }
if (result.Failed) if (result.Failed)
throw new ApplicationException(result.Error); throw new DownloadClientException("Error response received from SABnzbd: {0}", result.Error);
} }
//TODO: Find a better home for this //TODO: Find a better home for this

View File

@ -59,10 +59,10 @@ namespace NzbDrone.Core.Download.Clients.Sabnzbd
[FieldDefinition(5, Label = "Category", Type = FieldType.Textbox)] [FieldDefinition(5, Label = "Category", Type = FieldType.Textbox)]
public String TvCategory { get; set; } public String TvCategory { get; set; }
[FieldDefinition(6, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(SabnzbdPriority))] [FieldDefinition(6, Label = "Recent Priority", Type = FieldType.Select, SelectOptions = typeof(SabnzbdPriority), HelpText = "Priority to use when grabbing episodes that aired within the last 14 days")]
public Int32 RecentTvPriority { get; set; } public Int32 RecentTvPriority { get; set; }
[FieldDefinition(7, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(SabnzbdPriority))] [FieldDefinition(7, Label = "Older Priority", Type = FieldType.Select, SelectOptions = typeof(SabnzbdPriority), HelpText = "Priority to use when grabbing episodes that aired over 14 days ago")]
public Int32 OlderTvPriority { get; set; } public Int32 OlderTvPriority { get; set; }
[FieldDefinition(8, Label = "Use SSL", Type = FieldType.Checkbox)] [FieldDefinition(8, Label = "Use SSL", Type = FieldType.Checkbox)]

View File

@ -44,5 +44,6 @@ namespace NzbDrone.Core.Download
public abstract IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 10); public abstract IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 10);
public abstract void RemoveFromQueue(string id); public abstract void RemoveFromQueue(string id);
public abstract void RemoveFromHistory(string id); public abstract void RemoveFromHistory(string id);
public abstract void Test();
} }
} }

View File

@ -2,6 +2,7 @@
using System.Linq; using System.Linq;
using NLog; using NLog;
using NzbDrone.Common.Composition; using NzbDrone.Common.Composition;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.ThingiProvider; using NzbDrone.Core.ThingiProvider;
namespace NzbDrone.Core.Download namespace NzbDrone.Core.Download
@ -15,8 +16,8 @@ namespace NzbDrone.Core.Download
{ {
private readonly IDownloadClientRepository _providerRepository; private readonly IDownloadClientRepository _providerRepository;
public DownloadClientFactory(IDownloadClientRepository providerRepository, IEnumerable<IDownloadClient> providers, IContainer container, Logger logger) public DownloadClientFactory(IDownloadClientRepository providerRepository, IEnumerable<IDownloadClient> providers, IContainer container, IEventAggregator eventAggregator, Logger logger)
: base(providerRepository, providers, container, logger) : base(providerRepository, providers, container, eventAggregator, logger)
{ {
_providerRepository = providerRepository; _providerRepository = providerRepository;
} }

View File

@ -1,9 +1,4 @@
using System.Collections.Generic; using System.Linq;
using System.Linq;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Download.Clients;
using NzbDrone.Core.Download.Clients.Nzbget;
using NzbDrone.Core.Download.Clients.Sabnzbd;
namespace NzbDrone.Core.Download namespace NzbDrone.Core.Download
{ {

View File

@ -1,6 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using NLog; using NLog;
using NzbDrone.Common;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.History; using NzbDrone.Core.History;
using NzbDrone.Core.Messaging.Commands; using NzbDrone.Core.Messaging.Commands;
@ -72,8 +73,7 @@ namespace NzbDrone.Core.Download
continue; continue;
} }
if (failedHistory.Any(h => h.Data.ContainsKey(DOWNLOAD_CLIENT_ID) && if (failedHistory.Any(h => failedLocal.Id.Equals(h.Data.GetValueOrDefault(DOWNLOAD_CLIENT_ID))))
h.Data[DOWNLOAD_CLIENT_ID].Equals(failedLocal.Id)))
{ {
_logger.Trace("Already added to history as failed"); _logger.Trace("Already added to history as failed");
continue; continue;
@ -118,8 +118,7 @@ namespace NzbDrone.Core.Download
continue; continue;
} }
if (failedHistory.Any(h => h.Data.ContainsKey(DOWNLOAD_CLIENT_ID) && if (failedHistory.Any(h => failedLocal.Id.Equals(h.Data.GetValueOrDefault(DOWNLOAD_CLIENT_ID))))
h.Data[DOWNLOAD_CLIENT_ID].Equals(failedLocal.Id)))
{ {
_logger.Trace("Already added to history as failed"); _logger.Trace("Already added to history as failed");
continue; continue;
@ -137,8 +136,7 @@ namespace NzbDrone.Core.Download
private List<History.History> GetHistoryItems(List<History.History> grabbedHistory, string downloadClientId) private List<History.History> GetHistoryItems(List<History.History> grabbedHistory, string downloadClientId)
{ {
return grabbedHistory.Where(h => h.Data.ContainsKey(DOWNLOAD_CLIENT_ID) && return grabbedHistory.Where(h => downloadClientId.Equals(h.Data.GetValueOrDefault(DOWNLOAD_CLIENT_ID)))
h.Data[DOWNLOAD_CLIENT_ID].Equals(downloadClientId))
.ToList(); .ToList();
} }
@ -148,17 +146,14 @@ namespace NzbDrone.Core.Download
string downloadClient; string downloadClient;
string downloadClientId; string downloadClientId;
historyItem.Data.TryGetValue(DOWNLOAD_CLIENT, out downloadClient);
historyItem.Data.TryGetValue(DOWNLOAD_CLIENT_ID, out downloadClientId);
_eventAggregator.PublishEvent(new DownloadFailedEvent _eventAggregator.PublishEvent(new DownloadFailedEvent
{ {
SeriesId = historyItem.SeriesId, SeriesId = historyItem.SeriesId,
EpisodeIds = historyItems.Select(h => h.EpisodeId).ToList(), EpisodeIds = historyItems.Select(h => h.EpisodeId).ToList(),
Quality = historyItem.Quality, Quality = historyItem.Quality,
SourceTitle = historyItem.SourceTitle, SourceTitle = historyItem.SourceTitle,
DownloadClient = downloadClient, DownloadClient = historyItem.Data.GetValueOrDefault(DOWNLOAD_CLIENT),
DownloadClientId = downloadClientId, DownloadClientId = historyItem.Data.GetValueOrDefault(DOWNLOAD_CLIENT_ID),
Message = message Message = message
}); });
} }

View File

@ -11,5 +11,6 @@ namespace NzbDrone.Core.Download
IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 0); IEnumerable<HistoryItem> GetHistory(int start = 0, int limit = 0);
void RemoveFromQueue(string id); void RemoveFromQueue(string id);
void RemoveFromHistory(string id); void RemoveFromHistory(string id);
void Test();
} }
} }

View File

@ -0,0 +1,8 @@
using NzbDrone.Core.Messaging.Commands;
namespace NzbDrone.Core.HealthCheck
{
public class CheckHealthCommand : Command
{
}
}

View File

@ -0,0 +1,36 @@
using System;
using NzbDrone.Core.Download;
namespace NzbDrone.Core.HealthCheck.Checks
{
public class DownloadClientCheck : IProvideHealthCheck
{
private readonly IProvideDownloadClient _downloadClientProvider;
public DownloadClientCheck(IProvideDownloadClient downloadClientProvider)
{
_downloadClientProvider = downloadClientProvider;
}
public HealthCheck Check()
{
var downloadClient = _downloadClientProvider.GetDownloadClient();
if (downloadClient == null)
{
return new HealthCheck(HealthCheckResultType.Warning, "No download client is available");
}
try
{
downloadClient.GetQueue();
}
catch (Exception)
{
return new HealthCheck(HealthCheckResultType.Error, "Unable to communicate with download client");
}
return null;
}
}
}

View File

@ -0,0 +1,50 @@
using System;
using System.IO;
using NzbDrone.Common;
using NzbDrone.Common.Disk;
using NzbDrone.Core.Configuration;
namespace NzbDrone.Core.HealthCheck.Checks
{
public class DroneFactoryCheck : IProvideHealthCheck
{
private readonly IConfigService _configService;
private readonly IDiskProvider _diskProvider;
public DroneFactoryCheck(IConfigService configService, IDiskProvider diskProvider)
{
_configService = configService;
_diskProvider = diskProvider;
}
public HealthCheck Check()
{
var droneFactoryFolder = _configService.DownloadedEpisodesFolder;
if (droneFactoryFolder.IsNullOrWhiteSpace())
{
return new HealthCheck(HealthCheckResultType.Warning, "Drone factory folder is not configured");
}
if (!_diskProvider.FolderExists(droneFactoryFolder))
{
return new HealthCheck(HealthCheckResultType.Error, "Drone factory folder does not exist");
}
try
{
var testPath = Path.Combine(droneFactoryFolder, "drone_test.txt");
_diskProvider.WriteAllText(testPath, DateTime.Now.ToString());
_diskProvider.DeleteFile(testPath);
}
catch (Exception)
{
return new HealthCheck(HealthCheckResultType.Error, "Unable to write to drone factory folder");
}
//Todo: Unable to import one or more files/folders from
return null;
}
}
}

View File

@ -0,0 +1,32 @@
using System.Linq;
using NzbDrone.Core.Indexers;
namespace NzbDrone.Core.HealthCheck.Checks
{
public class IndexerCheck : IProvideHealthCheck
{
private readonly IIndexerFactory _indexerFactory;
public IndexerCheck(IIndexerFactory indexerFactory)
{
_indexerFactory = indexerFactory;
}
public HealthCheck Check()
{
var enabled = _indexerFactory.GetAvailableProviders();
if (!enabled.Any())
{
return new HealthCheck(HealthCheckResultType.Error, "No indexers are enabled");
}
if (enabled.All(i => i.SupportsSearching == false))
{
return new HealthCheck(HealthCheckResultType.Warning, "Enabled indexers do not support searching");
}
return null;
}
}
}

View File

@ -0,0 +1,51 @@
using System;
using System.IO;
using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Core.Update;
namespace NzbDrone.Core.HealthCheck.Checks
{
public class UpdateCheck : IProvideHealthCheck
{
private readonly IDiskProvider _diskProvider;
private readonly IAppFolderInfo _appFolderInfo;
private readonly ICheckUpdateService _checkUpdateService;
public UpdateCheck(IDiskProvider diskProvider, IAppFolderInfo appFolderInfo, ICheckUpdateService checkUpdateService)
{
_diskProvider = diskProvider;
_appFolderInfo = appFolderInfo;
_checkUpdateService = checkUpdateService;
}
public HealthCheck Check()
{
if (OsInfo.IsWindows)
{
try
{
var testPath = Path.Combine(_appFolderInfo.StartUpFolder, "drone_test.txt");
_diskProvider.WriteAllText(testPath, DateTime.Now.ToString());
_diskProvider.DeleteFile(testPath);
}
catch (Exception)
{
return new HealthCheck(HealthCheckResultType.Error,
"Unable to update, running from write-protected folder");
}
}
if (BuildInfo.BuildDateTime < DateTime.UtcNow.AddDays(-14))
{
if (_checkUpdateService.AvailableUpdate() != null)
{
return new HealthCheck(HealthCheckResultType.Warning, "New update is available");
}
}
return null;
}
}
}

View File

@ -0,0 +1,23 @@
using System;
using NzbDrone.Core.Datastore;
namespace NzbDrone.Core.HealthCheck
{
public class HealthCheck : ModelBase
{
public HealthCheckResultType Type { get; set; }
public String Message { get; set; }
public HealthCheck(HealthCheckResultType type, string message)
{
Type = type;
Message = message;
}
}
public enum HealthCheckResultType
{
Warning = 1,
Error = 2
}
}

View File

@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Core.Configuration.Events;
using NzbDrone.Core.Download;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Messaging.Commands;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.ThingiProvider.Events;
namespace NzbDrone.Core.HealthCheck
{
public interface IHealthCheckService
{
List<HealthCheck> PerformHealthCheck();
}
public class HealthCheckService : IHealthCheckService,
IExecute<CheckHealthCommand>,
IHandleAsync<ConfigSavedEvent>,
IHandleAsync<ProviderUpdatedEvent<IIndexer>>,
IHandleAsync<ProviderUpdatedEvent<IDownloadClient>>
{
private readonly IEnumerable<IProvideHealthCheck> _healthChecks;
private readonly IEventAggregator _eventAggregator;
private readonly Logger _logger;
public HealthCheckService(IEnumerable<IProvideHealthCheck> healthChecks, IEventAggregator eventAggregator, Logger logger)
{
_healthChecks = healthChecks;
_eventAggregator = eventAggregator;
_logger = logger;
}
public List<HealthCheck> PerformHealthCheck()
{
_logger.Trace("Checking health");
var result = _healthChecks.Select(c => c.Check()).Where(c => c != null).ToList();
return result;
}
public void Execute(CheckHealthCommand message)
{
//Until we have stored health checks we should just trigger the complete event
//and let the clients check in
//Multiple connected clients means we're going to compute the health check multiple times
//Multiple checks feels a bit ugly, but means the most up to date information goes to the client
_eventAggregator.PublishEvent(new TriggerHealthCheckEvent());
}
public void HandleAsync(ConfigSavedEvent message)
{
_eventAggregator.PublishEvent(new TriggerHealthCheckEvent());
}
public void HandleAsync(ProviderUpdatedEvent<IIndexer> message)
{
_eventAggregator.PublishEvent(new TriggerHealthCheckEvent());
}
public void HandleAsync(ProviderUpdatedEvent<IDownloadClient> message)
{
_eventAggregator.PublishEvent(new TriggerHealthCheckEvent());
}
}
}

View File

@ -0,0 +1,7 @@
namespace NzbDrone.Core.HealthCheck
{
public interface IProvideHealthCheck
{
HealthCheck Check();
}
}

View File

@ -0,0 +1,8 @@
using NzbDrone.Common.Messaging;
namespace NzbDrone.Core.HealthCheck
{
public class TriggerHealthCheckEvent : IEvent
{
}
}

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using Marr.Data.QGen; using Marr.Data.QGen;
using NzbDrone.Core.Datastore; using NzbDrone.Core.Datastore;
using NzbDrone.Core.Datastore.Extentions;
using NzbDrone.Core.Messaging.Events; using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Qualities; using NzbDrone.Core.Qualities;
using NzbDrone.Core.Tv; using NzbDrone.Core.Tv;

View File

@ -9,6 +9,7 @@ namespace NzbDrone.Core.Indexers
IParseFeed Parser { get; } IParseFeed Parser { get; }
DownloadProtocol Protocol { get; } DownloadProtocol Protocol { get; }
Boolean SupportsPaging { get; } Boolean SupportsPaging { get; }
Boolean SupportsSearching { get; }
IEnumerable<string> RecentFeed { get; } IEnumerable<string> RecentFeed { get; }
IEnumerable<string> GetEpisodeSearchUrls(string seriesTitle, int tvRageId, int seasonNumber, int episodeNumber); IEnumerable<string> GetEpisodeSearchUrls(string seriesTitle, int tvRageId, int seasonNumber, int episodeNumber);

View File

@ -35,6 +35,7 @@ namespace NzbDrone.Core.Indexers
public abstract DownloadProtocol Protocol { get; } public abstract DownloadProtocol Protocol { get; }
public abstract bool SupportsPaging { get; } public abstract bool SupportsPaging { get; }
public virtual bool SupportsSearching { get { return true; } }
protected TSettings Settings protected TSettings Settings
{ {

View File

@ -2,6 +2,7 @@
using System.Linq; using System.Linq;
using NLog; using NLog;
using NzbDrone.Common.Composition; using NzbDrone.Common.Composition;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.ThingiProvider; using NzbDrone.Core.ThingiProvider;
namespace NzbDrone.Core.Indexers namespace NzbDrone.Core.Indexers
@ -16,8 +17,13 @@ namespace NzbDrone.Core.Indexers
private readonly IIndexerRepository _providerRepository; private readonly IIndexerRepository _providerRepository;
private readonly INewznabTestService _newznabTestService; private readonly INewznabTestService _newznabTestService;
public IndexerFactory(IIndexerRepository providerRepository, IEnumerable<IIndexer> providers, IContainer container, INewznabTestService newznabTestService, Logger logger) public IndexerFactory(IIndexerRepository providerRepository,
: base(providerRepository, providers, container, logger) IEnumerable<IIndexer> providers,
IContainer container,
IEventAggregator eventAggregator,
INewznabTestService newznabTestService,
Logger logger)
: base(providerRepository, providers, container, eventAggregator, logger)
{ {
_providerRepository = providerRepository; _providerRepository = providerRepository;
_newznabTestService = newznabTestService; _newznabTestService = newznabTestService;

View File

@ -17,12 +17,11 @@ namespace NzbDrone.Core.Indexers.Newznab
var code = Convert.ToInt32(error.Attribute("code").Value); var code = Convert.ToInt32(error.Attribute("code").Value);
var errorMessage = error.Attribute("description").Value; var errorMessage = error.Attribute("description").Value;
if (code >= 100 && code <= 199) throw new ApiKeyException("Invalid API key"); if (code >= 100 && code <= 199) throw new ApiKeyException("Invalid API key");
if (!url.Contains("apikey=") && errorMessage == "Missing parameter") if (!url.Contains("apikey=") && errorMessage == "Missing parameter")
{ {
throw new ApiKeyException("Indexer requires and API key"); throw new ApiKeyException("Indexer requires an API key");
} }
throw new NewznabException("Newznab error detected: {0}", errorMessage); throw new NewznabException("Newznab error detected: {0}", errorMessage);

View File

@ -48,11 +48,11 @@ namespace NzbDrone.Core.Indexers
var apiKeyFailure = new ValidationFailure("ApiKey", "Invalid API Key"); var apiKeyFailure = new ValidationFailure("ApiKey", "Invalid API Key");
throw new ValidationException(new List<ValidationFailure> { apiKeyFailure }.ToArray()); throw new ValidationException(new List<ValidationFailure> { apiKeyFailure }.ToArray());
} }
catch (Exception) catch (Exception ex)
{ {
_logger.Warn("Indexer doesn't appear to be Newznab based"); _logger.WarnException("Indexer doesn't appear to be Newznab based: " + ex.Message, ex);
var failure = new ValidationFailure("Url", "Invalid Newznab URL entered"); var failure = new ValidationFailure("Url", "Invalid Newznab URL, check log for details");
throw new ValidationException(new List<ValidationFailure> { failure }.ToArray()); throw new ValidationException(new List<ValidationFailure> { failure }.ToArray());
} }
} }

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