diff --git a/NzbDrone.Api/RootFolders/RootFolderModule.cs b/NzbDrone.Api/RootFolders/RootFolderModule.cs index 306b2d61c..46c39dd3a 100644 --- a/NzbDrone.Api/RootFolders/RootFolderModule.cs +++ b/NzbDrone.Api/RootFolders/RootFolderModule.cs @@ -3,17 +3,18 @@ using Nancy; using NzbDrone.Api.Extentions; using NzbDrone.Core.Providers; using NzbDrone.Core.Repository; +using NzbDrone.Core.RootFolders; namespace NzbDrone.Api.RootFolders { public class RootDirModule : NzbDroneApiModule { - private readonly RootDirProvider _rootDirProvider; + private readonly RootFolderService _rootFolderService; - public RootDirModule(RootDirProvider rootDirProvider) + public RootDirModule(RootFolderService rootFolderService) : base("//rootdir") { - _rootDirProvider = rootDirProvider; + _rootFolderService = rootFolderService; Get["/"] = x => GetRootFolders(); Post["/"] = x => AddRootFolder(); @@ -22,18 +23,18 @@ namespace NzbDrone.Api.RootFolders private Response AddRootFolder() { - var dir = _rootDirProvider.Add(Request.Body.FromJson()); + var dir = _rootFolderService.Add(Request.Body.FromJson()); return dir.AsResponse(HttpStatusCode.Created); } private Response GetRootFolders() { - return _rootDirProvider.AllWithFreeSpace().AsResponse(); + return _rootFolderService.All().AsResponse(); } private Response DeleteRootFolder(int folderId) { - _rootDirProvider.Remove(folderId); + _rootFolderService.Remove(folderId); return new Response { StatusCode = HttpStatusCode.OK }; } } diff --git a/NzbDrone.Common/EnvironmentProvider.cs b/NzbDrone.Common/EnvironmentProvider.cs index 1cd2ffcee..616819ab4 100644 --- a/NzbDrone.Common/EnvironmentProvider.cs +++ b/NzbDrone.Common/EnvironmentProvider.cs @@ -107,7 +107,15 @@ namespace NzbDrone.Common { get { - return new FileInfo(Assembly.GetExecutingAssembly().Location).Directory.FullName; + var path = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory.FullName; + + if (path.StartsWith(Environment.GetFolderPath(Environment.SpecialFolder.Windows), + StringComparison.InvariantCultureIgnoreCase)) + { + path = Directory.GetCurrentDirectory(); + } + + return path; } } diff --git a/NzbDrone.Common/PathExtentions.cs b/NzbDrone.Common/PathExtentions.cs index 6a3058115..5eefc625a 100644 --- a/NzbDrone.Common/PathExtentions.cs +++ b/NzbDrone.Common/PathExtentions.cs @@ -7,6 +7,7 @@ namespace NzbDrone.Common { private const string WEB_FOLDER = "NzbDrone.Web\\"; private const string APP_DATA = "App_Data\\"; + private const string WEB_BIN = "bin\\"; public const string IIS_FOLDER = "IISExpress"; public const string IIS_EXE = "iisexpress.exe"; @@ -70,6 +71,11 @@ namespace NzbDrone.Common return Path.Combine(environmentProvider.GetWebRoot(), APP_DATA); } + public static string GetWebBinPath(this EnvironmentProvider environmentProvider) + { + return Path.Combine(environmentProvider.GetWebRoot(), WEB_BIN); + } + public static string GetNlogConfigPath(this EnvironmentProvider environmentProvider) { return Path.Combine(environmentProvider.GetWebRoot(), LOG_CONFIG_FILE); diff --git a/NzbDrone.Core.Test/Datastore/ObjectDatabaseFixture.cs b/NzbDrone.Core.Test/Datastore/ObjectDatabaseFixture.cs index cd96feb4e..cadc86a33 100644 --- a/NzbDrone.Core.Test/Datastore/ObjectDatabaseFixture.cs +++ b/NzbDrone.Core.Test/Datastore/ObjectDatabaseFixture.cs @@ -1,4 +1,5 @@ using System.Linq; +using Eloquera.Client; using FizzWare.NBuilder; using FluentAssertions; using NUnit.Framework; @@ -82,6 +83,19 @@ namespace NzbDrone.Core.Test.Datastore Db.Insert(testSeries); testSeries.Id.Should().NotBe(0); } + + [Test] + public void should_be_able_to_read_unknow_type() + { + Db.AsQueryable().ToList().Should().BeEmpty(); + } + } + + public class UnKnowType + { + [ID] + public string Id; + public string Field1 { get; set; } } } diff --git a/NzbDrone.Core.Test/Framework/ObjectDbTest.cs b/NzbDrone.Core.Test/Framework/ObjectDbTest.cs index 897810a91..e0a13ecca 100644 --- a/NzbDrone.Core.Test/Framework/ObjectDbTest.cs +++ b/NzbDrone.Core.Test/Framework/ObjectDbTest.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using NUnit.Framework; +using NzbDrone.Common; using NzbDrone.Core.Datastore; namespace NzbDrone.Core.Test.Framework @@ -23,11 +24,11 @@ namespace NzbDrone.Core.Test.Framework { if (memory) { - _db = new EloqueraDbFactory().CreateMemoryDb(); + _db = new EloqueraDbFactory(new EnvironmentProvider()).CreateMemoryDb(); } else { - _db = new EloqueraDbFactory().Create(Guid.NewGuid().ToString()); + _db = new EloqueraDbFactory(new EnvironmentProvider()).Create(); } Mocker.SetConstant(Db); diff --git a/NzbDrone.Core.Test/Framework/SqlCeTest.cs b/NzbDrone.Core.Test/Framework/SqlCeTest.cs index c47dd737c..89bf44cda 100644 --- a/NzbDrone.Core.Test/Framework/SqlCeTest.cs +++ b/NzbDrone.Core.Test/Framework/SqlCeTest.cs @@ -28,6 +28,32 @@ namespace NzbDrone.Core.Test.Framework } + public abstract class CoreTest : CoreTest + { + private TSubject _subject; + + + protected TSubject Subject + { + get + { + if (_subject == null) + { + _subject = Mocker.Resolve(); + } + + return _subject; + + } + } + + + protected void InitiateSubject() + { + _subject = Mocker.Resolve(); + } + } + public abstract class SqlCeTest : CoreTest { diff --git a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj index 8862d93d8..33e889883 100644 --- a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -79,6 +79,7 @@ ..\packages\EloqueraDB.5.0.0\lib\net40\Eloquera.Server.exe + True ..\packages\NBuilder.3.0.1.1\lib\FizzWare.NBuilder.dll diff --git a/NzbDrone.Core.Test/NzbDrone.Core.Test.ncrunchproject b/NzbDrone.Core.Test/NzbDrone.Core.Test.ncrunchproject index 9812b56a3..ab51924af 100644 --- a/NzbDrone.Core.Test/NzbDrone.Core.Test.ncrunchproject +++ b/NzbDrone.Core.Test/NzbDrone.Core.Test.ncrunchproject @@ -31,5 +31,6 @@ NzbDrone\.Core\.Test\.Integeration\.ServiceIntegerationFixture\..* + ..\NzbDrone.Core\bin\Debug\Eloquera.Server.exe PostBuildEventDisabled \ No newline at end of file diff --git a/NzbDrone.Core.Test/ProviderTests/RootDirProviderTests/FreeSpaceOnDrivesFixture.cs b/NzbDrone.Core.Test/ProviderTests/RootDirProviderTests/FreeSpaceOnDrivesFixture.cs index aadb33bf7..fb5902d53 100644 --- a/NzbDrone.Core.Test/ProviderTests/RootDirProviderTests/FreeSpaceOnDrivesFixture.cs +++ b/NzbDrone.Core.Test/ProviderTests/RootDirProviderTests/FreeSpaceOnDrivesFixture.cs @@ -12,6 +12,7 @@ using NzbDrone.Common; using NzbDrone.Core.Providers; using NzbDrone.Core.Providers.Core; using NzbDrone.Core.Repository; +using NzbDrone.Core.RootFolders; using NzbDrone.Core.Test.Framework; using NzbDrone.Test.Common; using NzbDrone.Test.Common.AutoMoq; @@ -38,7 +39,7 @@ namespace NzbDrone.Core.Test.ProviderTests.RootDirProviderTests .Setup(s => s.FreeDiskSpace(new DirectoryInfo(@"C:\"))) .Returns(123456); - var result = Mocker.Resolve().FreeSpaceOnDrives(); + var result = Mocker.Resolve().FreeSpaceOnDrives(); result.Should().HaveCount(1); } @@ -59,7 +60,7 @@ namespace NzbDrone.Core.Test.ProviderTests.RootDirProviderTests .Setup(s => s.FreeDiskSpace(new DirectoryInfo(@"C:\"))) .Returns(123456); - var result = Mocker.Resolve().FreeSpaceOnDrives(); + var result = Mocker.Resolve().FreeSpaceOnDrives(); result.Should().HaveCount(1); } @@ -84,7 +85,7 @@ namespace NzbDrone.Core.Test.ProviderTests.RootDirProviderTests .Setup(s => s.FreeDiskSpace(It.IsAny())) .Returns(123456); - var result = Mocker.Resolve().FreeSpaceOnDrives(); + var result = Mocker.Resolve().FreeSpaceOnDrives(); result.Should().HaveCount(2); } @@ -104,7 +105,7 @@ namespace NzbDrone.Core.Test.ProviderTests.RootDirProviderTests .Setup(s => s.FreeDiskSpace(It.IsAny())) .Throws(new DirectoryNotFoundException()); - var result = Mocker.Resolve().FreeSpaceOnDrives(); + var result = Mocker.Resolve().FreeSpaceOnDrives(); result.Should().HaveCount(0); diff --git a/NzbDrone.Core.Test/ProviderTests/RootDirProviderTests/RootDirProviderFixture.cs b/NzbDrone.Core.Test/ProviderTests/RootDirProviderTests/RootDirProviderFixture.cs index a7701dcc3..111ac0ade 100644 --- a/NzbDrone.Core.Test/ProviderTests/RootDirProviderTests/RootDirProviderFixture.cs +++ b/NzbDrone.Core.Test/ProviderTests/RootDirProviderTests/RootDirProviderFixture.cs @@ -1,6 +1,7 @@ // ReSharper disable RedundantUsingDirective using System; +using System.Collections.Generic; using System.IO; using System.Linq; @@ -11,6 +12,7 @@ using NzbDrone.Common; using NzbDrone.Core.Providers; using NzbDrone.Core.Providers.Core; using NzbDrone.Core.Repository; +using NzbDrone.Core.RootFolders; using NzbDrone.Core.Test.Framework; using NzbDrone.Test.Common.AutoMoq; @@ -18,7 +20,7 @@ namespace NzbDrone.Core.Test.ProviderTests.RootDirProviderTests { [TestFixture] // ReSharper disable InconsistentNaming - public class RootDirProviderFixture : SqlCeTest + public class RootDirProviderFixture : CoreTest { [SetUp] public void Setup() @@ -35,32 +37,15 @@ namespace NzbDrone.Core.Test.ProviderTests.RootDirProviderTests .Returns(false); } - [Test] - public void GetRootDir_should_return_all_existing_roots() - { - WithRealDb(); - - Db.Insert(new RootDir { Path = @"C:\TV" }); - Db.Insert(new RootDir { Path = @"C:\TV2" }); - - var result = Mocker.Resolve().GetAll(); - result.Should().HaveCount(2); - } [TestCase("D:\\TV Shows\\")] [TestCase("//server//folder")] public void should_be_able_to_add_root_dir(string path) { - WithRealDb(); + var root = new RootDir { Path = path }; + Subject.Add(root); - //Act - var rootDirProvider = Mocker.Resolve(); - rootDirProvider.Add(new RootDir { Path = path }); - - //Assert - var rootDirs = rootDirProvider.GetAll(); - rootDirs.Should().HaveCount(1); - rootDirs.First().Path.Should().Be(path); + Mocker.GetMock().Verify(c => c.Add(root), Times.Once()); } [Test] @@ -68,34 +53,25 @@ namespace NzbDrone.Core.Test.ProviderTests.RootDirProviderTests { WithNoneExistingFolder(); - var rootDirProvider = Mocker.Resolve(); - Assert.Throws(() => rootDirProvider.Add(new RootDir { Path = "C:\\TEST" })); + Assert.Throws(() => Subject.Add(new RootDir { Path = "C:\\TEST" })); } [Test] public void should_be_able_to_remove_root_dir() { - WithRealDb(); - - //Act - var rootDirProvider = Mocker.Resolve(); - rootDirProvider.Add(new RootDir { Path = @"C:\TV" }); - rootDirProvider.Add(new RootDir { Path = @"C:\TV2" }); - rootDirProvider.Remove(1); - - //Assert - var rootDirs = rootDirProvider.GetAll(); - rootDirs.Should().HaveCount(1); + Subject.Remove(1); + Mocker.GetMock().Verify(c => c.Delete(1), Times.Once()); } - [Test] public void None_existing_folder_returns_empty_list() { WithNoneExistingFolder(); + Mocker.GetMock().Setup(c => c.All()).Returns(new List()); + const string path = "d:\\bad folder"; - var result = Mocker.Resolve().GetUnmappedFolders(path); + var result = Subject.GetUnmappedFolders(path); result.Should().NotBeNull(); result.Should().BeEmpty(); @@ -105,7 +81,7 @@ namespace NzbDrone.Core.Test.ProviderTests.RootDirProviderTests [Test] public void GetUnmappedFolders_throw_on_empty_folders() { - Assert.Throws(() => Mocker.Resolve().GetUnmappedFolders("")); + Assert.Throws(() => Mocker.Resolve().GetUnmappedFolders("")); } [TestCase("")] @@ -114,19 +90,17 @@ namespace NzbDrone.Core.Test.ProviderTests.RootDirProviderTests public void invalid_folder_path_throws_on_add(string path) { Assert.Throws(() => - Mocker.Resolve().Add(new RootDir { Id = 0, Path = path }) + Mocker.Resolve().Add(new RootDir { Id = 0, Path = path }) ); } [Test] public void adding_duplicated_root_folder_should_throw() { - WithRealDb(); + Mocker.GetMock().Setup(c => c.All()).Returns(new List { new RootDir { Path = "C:\\TV" } }); - //Act - var rootDirProvider = Mocker.Resolve(); - rootDirProvider.Add(new RootDir { Path = @"C:\TV" }); - Assert.Throws(() => rootDirProvider.Add(new RootDir { Path = @"C:\TV" })); + Subject.Add(new RootDir { Path = @"C:\TV" }); + Assert.Throws(() => Subject.Add(new RootDir { Path = @"C:\TV" })); } } } \ No newline at end of file diff --git a/NzbDrone.Core/ContainerExtentions.cs b/NzbDrone.Core/ContainerExtentions.cs index c76b35397..2f0c452cd 100644 --- a/NzbDrone.Core/ContainerExtentions.cs +++ b/NzbDrone.Core/ContainerExtentions.cs @@ -82,8 +82,7 @@ namespace NzbDrone.Core container.Register(c => { - var env = c.Resolve(); - return c.Resolve().Create(env.GetElqMainDbPath()); + return c.Resolve().Create(); }).As().SingleInstance(); container.RegisterType().WithParameter(ResolvedParameter.ForNamed("DatabaseTarget")); diff --git a/NzbDrone.Core/Datastore/EloqueraDb.cs b/NzbDrone.Core/Datastore/EloqueraDb.cs index 4cf96e9a1..be00281de 100644 --- a/NzbDrone.Core/Datastore/EloqueraDb.cs +++ b/NzbDrone.Core/Datastore/EloqueraDb.cs @@ -43,12 +43,12 @@ namespace NzbDrone.Core.Datastore } - public void Delete(T obj) + public void Delete(T obj) where T : new() { _db.Delete(obj); } - public void DeleteMany(IEnumerable objects) + public void DeleteMany(IEnumerable objects) where T: new() { foreach (var o in objects) { diff --git a/NzbDrone.Core/Datastore/EloqueraDbFactory.cs b/NzbDrone.Core/Datastore/EloqueraDbFactory.cs index 29dd92ed6..ec1d6fe5c 100644 --- a/NzbDrone.Core/Datastore/EloqueraDbFactory.cs +++ b/NzbDrone.Core/Datastore/EloqueraDbFactory.cs @@ -2,27 +2,52 @@ using System.IO; using System.Linq; using Eloquera.Client; +using NzbDrone.Common; namespace NzbDrone.Core.Datastore { public class EloqueraDbFactory { - public EloqueraDb CreateMemoryDb() + private readonly EnvironmentProvider _environmentProvider; + + private readonly string dllPath; + + public EloqueraDbFactory(EnvironmentProvider environmentProvider) { - return InternalCreate("server=(local);password=;options=inmemory;",Guid.NewGuid().ToString()); + _environmentProvider = environmentProvider; + dllPath = _environmentProvider.GetWebBinPath();// this is the path where Eloquera dlls live. } - public EloqueraDb Create(string dbPath) + public EloqueraDb CreateMemoryDb() { - var file = new FileInfo(dbPath).Name; - return InternalCreate(string.Format("server=(local);database={0};usedatapath={1};password=;", file, dbPath),file); + return InternalCreate("server=(local);password=;options=inmemory;uselocalpath=" + dllPath, Guid.NewGuid().ToString()); + } + + public EloqueraDb Create(string dbPath = null) + { + if (dbPath == null) + { + dbPath = _environmentProvider.GetElqMainDbPath(); + } + + var file = new FileInfo(dbPath); + + return InternalCreate(string.Format("server=(local);password=;usedatapath={0};uselocalpath={1}", file.Directory.FullName, dllPath), file.Name); } private EloqueraDb InternalCreate(string connectionString, string databaseName) { var db = new DB(connectionString); - db.CreateDatabase(databaseName); - db.OpenDatabase(databaseName); + try + { + db.OpenDatabase(databaseName); + } + catch (FileNotFoundException) + { + db.CreateDatabase(databaseName); + db.OpenDatabase(databaseName); + } + return new EloqueraDb(db); } diff --git a/NzbDrone.Core/Datastore/Migrations/Migration20130203.cs b/NzbDrone.Core/Datastore/Migrations/Migration20130203.cs new file mode 100644 index 000000000..795c82766 --- /dev/null +++ b/NzbDrone.Core/Datastore/Migrations/Migration20130203.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using Migrator.Framework; +using NzbDrone.Core.Repository; +using NzbDrone.Core.RootFolders; + +namespace NzbDrone.Core.Datastore.Migrations +{ + [Migration(20130203)] + public class Migration20130203 : NzbDroneMigration + { + protected override void MainDbUpgrade() + { + var objectDb = GetObjectDb(); + + + var rootFolderRepo = new RootFolderRepository(objectDb); + + + using (var dataReader = Database.ExecuteQuery("SELECT * from RootDirs")) + { + var dirs = new List(); + while (dataReader.Read()) + { + var rootFolder = new RootDir { Path = dataReader["Path"].ToString() }; + dirs.Add(rootFolder); + } + objectDb.InsertMany(dirs); + } + //Database.RemoveTable("RootDirs"); + + } + } +} \ No newline at end of file diff --git a/NzbDrone.Core/Datastore/Migrations/NzbDroneMigration.cs b/NzbDrone.Core/Datastore/Migrations/NzbDroneMigration.cs index cef596c3d..be0735e84 100644 --- a/NzbDrone.Core/Datastore/Migrations/NzbDroneMigration.cs +++ b/NzbDrone.Core/Datastore/Migrations/NzbDroneMigration.cs @@ -1,4 +1,5 @@ using System; +using System.Data.SqlServerCe; using System.Linq; using Migrator.Framework; using NzbDrone.Common; @@ -32,6 +33,14 @@ namespace NzbDrone.Core.Datastore.Migrations } } + protected EloqueraDb GetObjectDb() + { + + var sqlCeConnection = new SqlCeConnection(Database.ConnectionString); + + var eqPath = sqlCeConnection.Database.Replace(".sdf", ".eq"); + return new EloqueraDbFactory(new EnvironmentProvider()).Create(eqPath); + } public override void Down() { diff --git a/NzbDrone.Core/Datastore/MigrationsHelper.cs b/NzbDrone.Core/Datastore/MigrationsHelper.cs index 6de4814cf..801ce1ed5 100644 --- a/NzbDrone.Core/Datastore/MigrationsHelper.cs +++ b/NzbDrone.Core/Datastore/MigrationsHelper.cs @@ -9,37 +9,37 @@ namespace NzbDrone.Core.Datastore { public class MigrationsHelper { - private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + private static readonly Logger logger = LogManager.GetCurrentClassLogger(); - public static void Run(string connetionString, bool trace) + public static void Run(string connectionString, bool trace) { - EnsureDatabase(connetionString); + EnsureDatabase(connectionString); - Logger.Trace("Preparing to run database migration"); + logger.Trace("Preparing to run database migration"); try { Migrator.Migrator migrator; if (trace) { - migrator = new Migrator.Migrator("sqlserverce", connetionString, Assembly.GetAssembly(typeof(MigrationsHelper)), true, new MigrationLogger()); + migrator = new Migrator.Migrator("sqlserverce", connectionString, Assembly.GetAssembly(typeof(MigrationsHelper)), true, new MigrationLogger()); } else { - migrator = new Migrator.Migrator("sqlserverce", connetionString, Assembly.GetAssembly(typeof(MigrationsHelper))); + migrator = new Migrator.Migrator("sqlserverce", connectionString, Assembly.GetAssembly(typeof(MigrationsHelper))); } migrator.MigrateToLastVersion(); - Logger.Info("Database migration completed"); + logger.Info("Database migration completed"); } catch (Exception e) { - Logger.FatalException("An error has occurred while migrating database", e); + logger.FatalException("An error has occurred while migrating database", e); throw; } } diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index 56b2b5300..777e7997d 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -237,6 +237,7 @@ + @@ -536,7 +537,7 @@ Code - + Code @@ -599,6 +600,7 @@ + diff --git a/NzbDrone.Core/Repository/RootDir.cs b/NzbDrone.Core/Repository/RootDir.cs index 3003dbf6f..7cb43d9e4 100644 --- a/NzbDrone.Core/Repository/RootDir.cs +++ b/NzbDrone.Core/Repository/RootDir.cs @@ -3,9 +3,21 @@ using PetaPoco; namespace NzbDrone.Core.Repository { + public interface IRootDir + { + int Id { get; set; } + string Path { get; set; } + + [ResultColumn] + ulong FreeSpace { get; set; } + + [Ignore] + List UnmappedFolders { get; set; } + } + [TableName("RootDirs")] [PrimaryKey("Id", autoIncrement = true)] - public class RootDir + public class RootDir : IRootDir { public virtual int Id { get; set; } diff --git a/NzbDrone.Core/RootFolders/RootFolderRepository.cs b/NzbDrone.Core/RootFolders/RootFolderRepository.cs new file mode 100644 index 000000000..3492c6a15 --- /dev/null +++ b/NzbDrone.Core/RootFolders/RootFolderRepository.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; +using NzbDrone.Core.Datastore; +using NzbDrone.Core.Repository; +using System.Linq; + +namespace NzbDrone.Core.RootFolders +{ + public interface IRootFolderRepository + { + List All(); + RootDir Get(int rootFolderId); + RootDir Add(RootDir rootFolder); + void Delete(int rootFolderId); + } + + public class RootFolderRepository : IRootFolderRepository + { + private readonly EloqueraDb _db; + + public RootFolderRepository(EloqueraDb db) + { + _db = db; + } + + public List All() + { + return _db.AsQueryable().ToList(); + } + + public RootDir Get(int rootFolderId) + { + return _db.AsQueryable().Single(c => c.Id == rootFolderId); + } + + public RootDir Add(RootDir rootFolder) + { + return _db.Insert(rootFolder); + } + + public void Delete(int rootFolderId) + { + _db.Delete(Get(rootFolderId)); + } + } + +} diff --git a/NzbDrone.Core/Providers/RootDirProvider.cs b/NzbDrone.Core/RootFolders/RootFolderService.cs similarity index 73% rename from NzbDrone.Core/Providers/RootDirProvider.cs rename to NzbDrone.Core/RootFolders/RootFolderService.cs index b28a4f03a..02b0de1e3 100644 --- a/NzbDrone.Core/Providers/RootDirProvider.cs +++ b/NzbDrone.Core/RootFolders/RootFolderService.cs @@ -1,30 +1,40 @@ -using System; +using System.Linq; +using System; using System.Collections.Generic; using System.IO; using NLog; using NzbDrone.Common; +using NzbDrone.Core.Providers; using NzbDrone.Core.Repository; -using PetaPoco; -namespace NzbDrone.Core.Providers +namespace NzbDrone.Core.RootFolders { - public class RootDirProvider + public interface IRootFolderService + { + List All(); + RootDir Add(RootDir rootDir); + void Remove(int rootDirId); + List GetUnmappedFolders(string path); + Dictionary FreeSpaceOnDrives(); + } + + public class RootFolderService : IRootFolderService { - private readonly IDatabase _database; private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + private readonly IRootFolderRepository _rootFolderRepository; private readonly DiskProvider _diskProvider; private readonly SeriesProvider _seriesProvider; - public RootDirProvider(IDatabase database, SeriesProvider seriesProvider, DiskProvider diskProvider) + public RootFolderService(IRootFolderRepository rootFolderRepository, SeriesProvider seriesProvider, DiskProvider diskProvider) { - _database = database; + _rootFolderRepository = rootFolderRepository; _diskProvider = diskProvider; _seriesProvider = seriesProvider; } - public virtual List GetAll() + public virtual List All() { - return _database.Fetch(); + return _rootFolderRepository.All(); } public virtual RootDir Add(RootDir rootDir) @@ -35,20 +45,19 @@ namespace NzbDrone.Core.Providers if (!_diskProvider.FolderExists(rootDir.Path)) throw new DirectoryNotFoundException("Can't add root directory that doesn't exist."); - if (GetAll().Exists(r => DiskProvider.PathEquals(r.Path, rootDir.Path))) + if (All().Exists(r => DiskProvider.PathEquals(r.Path, rootDir.Path))) throw new InvalidOperationException("Root directory already exist."); - var id = _database.Insert(rootDir); - rootDir.Id = Convert.ToInt32(id); + _rootFolderRepository.Add(rootDir); + rootDir.FreeSpace = _diskProvider.FreeDiskSpace(new DirectoryInfo(rootDir.Path)); rootDir.UnmappedFolders = GetUnmappedFolders(rootDir.Path); - return rootDir; } public virtual void Remove(int rootDirId) { - _database.Delete(rootDirId); + _rootFolderRepository.Delete(rootDirId); } public virtual List GetUnmappedFolders(string path) @@ -77,24 +86,12 @@ namespace NzbDrone.Core.Providers return results; } - public virtual List AllWithFreeSpace() - { - var rootDirs = GetAll(); - - foreach (var rootDir in rootDirs) - { - rootDir.FreeSpace = _diskProvider.FreeDiskSpace(new DirectoryInfo(rootDir.Path)); - rootDir.UnmappedFolders = GetUnmappedFolders(rootDir.Path); - } - - return rootDirs; - } public virtual Dictionary FreeSpaceOnDrives() { var freeSpace = new Dictionary(); - var rootDirs = GetAll(); + var rootDirs = All(); foreach (var rootDir in rootDirs) { diff --git a/NzbDrone.Services.Api/NzbDrone.Services.Api.csproj b/NzbDrone.Services.Api/NzbDrone.Services.Api.csproj index d135f28af..4e6d27d09 100644 --- a/NzbDrone.Services.Api/NzbDrone.Services.Api.csproj +++ b/NzbDrone.Services.Api/NzbDrone.Services.Api.csproj @@ -14,7 +14,7 @@ NzbDrone.Services.Api NzbDrone.Services.Api v4.0 - true + false @@ -150,9 +150,9 @@ True True - 0 + 1306 / - http://localhost:14615/ + http://localhost/NzbDrone.Services.Api False False diff --git a/NzbDrone.Web/App_Data/nzbdrone.eq b/NzbDrone.Web/App_Data/nzbdrone.eq new file mode 100644 index 000000000..2f4763722 Binary files /dev/null and b/NzbDrone.Web/App_Data/nzbdrone.eq differ diff --git a/NzbDrone.Web/Controllers/AddSeriesController.cs b/NzbDrone.Web/Controllers/AddSeriesController.cs deleted file mode 100644 index beff7c071..000000000 --- a/NzbDrone.Web/Controllers/AddSeriesController.cs +++ /dev/null @@ -1,188 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Web.Mvc; -using NLog; -using NzbDrone.Common; -using NzbDrone.Core.Jobs; -using NzbDrone.Core.Providers; -using NzbDrone.Core.Providers.Core; -using NzbDrone.Core.Repository; -using NzbDrone.Web.Filters; -using NzbDrone.Web.Models; -using TvdbLib.Exceptions; - -namespace NzbDrone.Web.Controllers -{ - public class AddSeriesController : Controller - { - private readonly ConfigProvider _configProvider; - private readonly QualityProvider _qualityProvider; - private readonly RootDirProvider _rootFolderProvider; - private readonly SeriesProvider _seriesProvider; - private readonly JobProvider _jobProvider; - private readonly TvDbProvider _tvDbProvider; - private readonly DiskProvider _diskProvider; - - private static readonly Logger logger = LogManager.GetCurrentClassLogger(); - - public AddSeriesController(RootDirProvider rootFolderProvider, - ConfigProvider configProvider, - QualityProvider qualityProvider, TvDbProvider tvDbProvider, - SeriesProvider seriesProvider, JobProvider jobProvider, - DiskProvider diskProvider) - { - - _rootFolderProvider = rootFolderProvider; - _configProvider = configProvider; - _qualityProvider = qualityProvider; - _tvDbProvider = tvDbProvider; - _seriesProvider = seriesProvider; - _jobProvider = jobProvider; - _diskProvider = diskProvider; - } - - public ActionResult Index() - { - return View(); - } - - public ActionResult AddNew() - { - ViewData["RootDirs"] = _rootFolderProvider.GetAll().Select(c => c.Path).OrderBy(e => e).ToList(); - - var defaultQuality = _configProvider.DefaultQualityProfile; - var qualityProfiles = _qualityProvider.All(); - - ViewData["qualityProfiles"] = new SelectList( - qualityProfiles, - "QualityProfileId", - "Name", - defaultQuality); - - return View(); - } - - public ActionResult ExistingSeries() - { - var result = new ExistingSeriesModel(); - - var unmappedList = new List(); - - foreach (var folder in _rootFolderProvider.GetAll()) - { - unmappedList.AddRange(_rootFolderProvider.GetUnmappedFolders(folder.Path)); - } - - result.ExistingSeries = new List>(); - - foreach (var folder in unmappedList) - { - var foldername = new DirectoryInfo(folder).Name; - - try - { - var tvdbResult = _tvDbProvider.SearchSeries(foldername).FirstOrDefault(); - - var title = String.Empty; - var seriesId = 0; - if (tvdbResult != null) - { - title = tvdbResult.SeriesName; - seriesId = tvdbResult.id; - } - - result.ExistingSeries.Add(new Tuple(folder, title, seriesId)); - } - catch (Exception ex) - { - logger.WarnException("Failed to connect to TheTVDB to search for: " + foldername, ex); - return View(); - } - } - - var defaultQuality = Convert.ToInt32(_configProvider.DefaultQualityProfile); - result.Quality = new SelectList(_qualityProvider.All(), "QualityProfileId", "Name", defaultQuality); - - return View(result); - } - - [HttpPost] - [JsonErrorFilter] - public JsonResult AddNewSeries(string path, string seriesName, int seriesId, int qualityProfileId, string startDate) - { - if (string.IsNullOrWhiteSpace(path) || String.Equals(path, "null", StringComparison.InvariantCultureIgnoreCase)) - return JsonNotificationResult.Error("Couldn't add " + seriesName, "You need a valid root folder"); - - path = Path.Combine(path, MediaFileProvider.CleanFilename(seriesName)); - - //Create the folder for the new series - //Use the created folder name when adding the series - path = _diskProvider.CreateDirectory(path); - - return AddExistingSeries(path, seriesName, seriesId, qualityProfileId, startDate); - } - - [HttpPost] - [JsonErrorFilter] - public JsonResult AddExistingSeries(string path, string seriesName, int seriesId, int qualityProfileId, string startDate) - { - if (seriesId == 0 || String.IsNullOrWhiteSpace(seriesName)) - return JsonNotificationResult.Error("Add Existing series failed.", "Invalid Series information"); - - DateTime? date = null; - - if (!String.IsNullOrWhiteSpace(startDate)) - date = DateTime.Parse(startDate, null, DateTimeStyles.RoundtripKind); - - _seriesProvider.AddSeries(seriesName, path, seriesId, qualityProfileId, date); - _jobProvider.QueueJob(typeof(ImportNewSeriesJob)); - - return JsonNotificationResult.Info(seriesName, "Was added successfully"); - } - - [HttpGet] - [JsonErrorFilter] - public JsonResult LookupSeries(string term) - { - - return JsonNotificationResult.Info("Lookup Failed", "Unknown error while connecting to TheTVDB"); - - } - - public ActionResult RootList() - { - IEnumerable rootDir = _rootFolderProvider.GetAll().Select(c => c.Path).OrderBy(e => e); - return PartialView("RootList", rootDir); - } - - public ActionResult RootDir() - { - return PartialView("RootDir"); - } - - [HttpPost] - [JsonErrorFilter] - public JsonResult SaveRootDir(string path) - { - if (String.IsNullOrWhiteSpace(path)) - JsonNotificationResult.Error("Can't add root folder", "Path can not be empty"); - - _rootFolderProvider.Add(new RootDir { Path = path }); - - return JsonNotificationResult.Info("Root Folder saved", "Root folder saved successfully."); - } - - [JsonErrorFilter] - public JsonResult DeleteRootDir(string path) - { - - var id = _rootFolderProvider.GetAll().Where(c => c.Path == path).First().Id; - _rootFolderProvider.Remove(id); - - return null; - } - } -} \ No newline at end of file diff --git a/NzbDrone.Web/Controllers/SharedController.cs b/NzbDrone.Web/Controllers/SharedController.cs index a4f43d8d5..3ca431803 100644 --- a/NzbDrone.Web/Controllers/SharedController.cs +++ b/NzbDrone.Web/Controllers/SharedController.cs @@ -1,6 +1,7 @@ using System.Web.Mvc; using NzbDrone.Common; using NzbDrone.Core.Providers; +using NzbDrone.Core.RootFolders; using NzbDrone.Web.Models; namespace NzbDrone.Web.Controllers @@ -8,12 +9,12 @@ namespace NzbDrone.Web.Controllers public class SharedController : Controller { private readonly EnvironmentProvider _environmentProvider; - private readonly RootDirProvider _rootDirProvider; + private readonly RootFolderService _rootFolderService; - public SharedController(EnvironmentProvider environmentProvider, RootDirProvider rootDirProvider) + public SharedController(EnvironmentProvider environmentProvider, RootFolderService rootFolderService) { _environmentProvider = environmentProvider; - _rootDirProvider = rootDirProvider; + _rootFolderService = rootFolderService; } public ActionResult Index() @@ -32,7 +33,7 @@ namespace NzbDrone.Web.Controllers [OutputCache(Duration = 600)] public ActionResult FreeSpace() { - var rootDirs = _rootDirProvider.FreeSpaceOnDrives(); + var rootDirs = _rootFolderService.FreeSpaceOnDrives(); return PartialView(rootDirs); } diff --git a/NzbDrone.Web/Eloquera.config b/NzbDrone.Web/Eloquera.config new file mode 100644 index 000000000..5ae536d21 --- /dev/null +++ b/NzbDrone.Web/Eloquera.config @@ -0,0 +1,31 @@ + + + + + + + + diff --git a/NzbDrone.Web/NzbDrone.Web.csproj b/NzbDrone.Web/NzbDrone.Web.csproj index 2340aaeee..bc97a5604 100644 --- a/NzbDrone.Web/NzbDrone.Web.csproj +++ b/NzbDrone.Web/NzbDrone.Web.csproj @@ -17,7 +17,7 @@ true false - false + true @@ -26,6 +26,10 @@ ..\ true \_backboneApp\JsLibraries\|\Scripts\ + + + + true @@ -88,6 +92,17 @@ ..\packages\DynamicQuery.1.0\lib\35\Dynamic.dll + + False + ..\packages\EloqueraDB.5.0.0\lib\net40\Eloquera.Client.dll + + + False + ..\packages\EloqueraDB.5.0.0\lib\net40\Eloquera.Common.dll + + + ..\packages\EloqueraDB.5.0.0\lib\net40\Eloquera.Server.exe + ..\packages\LowercaseRoutesMVC.1.0.3\lib\LowercaseRoutesMVC.dll @@ -341,7 +356,6 @@ - @@ -401,6 +415,7 @@ + @@ -606,8 +621,6 @@ - - Designer @@ -624,7 +637,6 @@ - @@ -666,15 +678,9 @@ - - - - - - diff --git a/NzbDrone.Web/Views/AddSeries/AddNew.cshtml b/NzbDrone.Web/Views/AddSeries/AddNew.cshtml deleted file mode 100644 index 9b86fb816..000000000 --- a/NzbDrone.Web/Views/AddSeries/AddNew.cshtml +++ /dev/null @@ -1,13 +0,0 @@ -@using System.Collections -@{ Layout = null; } -
-
- - @Html.Hidden("newSeriesId", 0, new { @class = "seriesId" }) -
- @Html.DropDownList("newSeriesPath", new SelectList((IList)ViewData["RootDirs"]), new { style = "width: 406px; margin-left: 0px;" }) - @Html.DropDownList("qualityList", (SelectList)ViewData["QualityProfiles"], new { @class = "qualitySelector" }) - @Html.TextBox("newStartDate", "", new { type = "date", @class = "jQuery-datepicker start-date", placeholder = "Custom Start Date", title = "Only download episodes that aired after the specified date" }) - -
\ No newline at end of file diff --git a/NzbDrone.Web/Views/AddSeries/ExistingSeries.cshtml b/NzbDrone.Web/Views/AddSeries/ExistingSeries.cshtml deleted file mode 100644 index 9f84db2e2..000000000 --- a/NzbDrone.Web/Views/AddSeries/ExistingSeries.cshtml +++ /dev/null @@ -1,44 +0,0 @@ -@using System.Collections -@using NzbDrone.Web.Models -@using System.Web.Mvc.Html -@model ExistingSeriesModel -@{ - Layout = null; -} - -@if (Model == null) -{ -

- Error searching TheTVDB, please try again later. -

-} - -else if (!Model.ExistingSeries.Any()) -{ -

- No series available. Try adding a new Root Folder. -

-} -else -{ - @Html.DropDownList(Guid.NewGuid().ToString(), Model.Quality, new { @class = "qualitySelector masterQualitySelector" }) - - @Html.TextBox(Guid.NewGuid().ToString(), "", new { type="date", @class = "jQuery-datepicker start-date-master", placeholder = "Custom Start Date", title = "Only download episodes that aired after the specified date" }) - - foreach (var series in Model.ExistingSeries) - { -
- - - -
- - @Html.Hidden("seriesId", series.Item3, new { @class = "seriesId" }) - @Html.DropDownList(Guid.NewGuid().ToString(), Model.Quality, new { @class = "qualitySelector" }) - @Html.TextBox(Guid.NewGuid().ToString(), "", new { type="date", @class = "jQuery-datepicker start-date", placeholder = "Custom Start Date", title = "Only download episodes that aired after the specified date" }) - -
-
- } -} diff --git a/NzbDrone.Web/Views/AddSeries/Index.cshtml b/NzbDrone.Web/Views/AddSeries/Index.cshtml deleted file mode 100644 index a9e15a06c..000000000 --- a/NzbDrone.Web/Views/AddSeries/Index.cshtml +++ /dev/null @@ -1,92 +0,0 @@ -@using NzbDrone.Web.Helpers -@{ViewBag.Title = "Add Series";} - -@section HeaderContent -{ - -} - -@{Html.RenderAction("RootDir");} -
-

- Add New Series

-
- @{ Html.RenderAction("AddNew", "AddSeries"); } -
-

- Add Series Already on Disk

-
- - - @Ajax.RenderAction( - "ExistingSeries", - "AddSeries", - null, - new AjaxOptions { UpdateTargetId = "existingSeries", InsertionMode = InsertionMode.Replace } - ) -
-
- -@section Scripts -{ - @Html.IncludeScript("NzbDrone/addSeries.js") - - -} \ No newline at end of file diff --git a/NzbDrone.Web/Views/AddSeries/RootDir.cshtml b/NzbDrone.Web/Views/AddSeries/RootDir.cshtml deleted file mode 100644 index fb5908da9..000000000 --- a/NzbDrone.Web/Views/AddSeries/RootDir.cshtml +++ /dev/null @@ -1,10 +0,0 @@ -

- Manage Root Folders -

- - - - - @{Html.RenderAction("RootList");} - diff --git a/NzbDrone.Web/Views/AddSeries/RootList.cshtml b/NzbDrone.Web/Views/AddSeries/RootList.cshtml deleted file mode 100644 index 95c1fdb9f..000000000 --- a/NzbDrone.Web/Views/AddSeries/RootList.cshtml +++ /dev/null @@ -1,16 +0,0 @@ -@model IEnumerable -@if (!Model.Any()) -{ -
- You have no root folders added. -
-} -@foreach (var root in Model) -{ -
-
- -
- @root -
-} diff --git a/NzbDrone.Web/Views/Series/Index.cshtml b/NzbDrone.Web/Views/Series/Index.cshtml index c9cb9f8e2..c747b70a1 100644 --- a/NzbDrone.Web/Views/Series/Index.cshtml +++ b/NzbDrone.Web/Views/Series/Index.cshtml @@ -5,16 +5,16 @@ { @Html.IncludeCss("Settings.css") } - @section ActionMenu{ @@ -61,7 +57,7 @@ - + @@ -70,7 +66,7 @@ - + @*Commands Column*@ @@ -96,7 +92,7 @@ @Html.IncludeScript("NzbDrone/series.js")
Status TitleNetwork Next Airing Episodes