More autoupdate code.

This commit is contained in:
kay.one 2011-11-12 20:07:06 -08:00
parent 95460b2134
commit 1270e464b3
25 changed files with 285 additions and 204 deletions

View File

@ -2,12 +2,20 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using NLog;
namespace NzbDrone.Common
{
public class DiskProvider
{
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetDiskFreeSpaceEx(string lpDirectoryName,
out ulong lpFreeBytesAvailable,
out ulong lpTotalNumberOfBytes,
out ulong lpTotalNumberOfFreeBytes);
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public virtual bool FolderExists(string path)
@ -47,6 +55,25 @@ namespace NzbDrone.Common
return Directory.CreateDirectory(path).FullName;
}
public virtual void CopyDirectory(string source, string target)
{
Logger.Trace("Copying {0} -> {1}", source, target);
var sourceFolder = new DirectoryInfo(source);
var targetFolder = new DirectoryInfo(target);
if (!targetFolder.Exists)
{
targetFolder.Create();
}
foreach (var file in sourceFolder.GetFiles("*.*", SearchOption.AllDirectories))
{
var destFile = Path.Combine(target, file.Name);
file.CopyTo(destFile, true);
}
}
public virtual void DeleteFile(string path)
{
File.Delete(path);
@ -77,30 +104,25 @@ namespace NzbDrone.Common
Directory.Move(source, destination);
}
public virtual void CopyDirectory(string source, string target)
{
Logger.Trace("Copying {0} -> {1}", source, target);
var sourceFolder = new DirectoryInfo(source);
var targetFolder = new DirectoryInfo(target);
if (!targetFolder.Exists)
{
targetFolder.Create();
}
foreach (var file in sourceFolder.GetFiles("*.*", SearchOption.AllDirectories))
{
var destFile = Path.Combine(target, file.Name);
file.CopyTo(destFile, true);
}
}
public virtual void InheritFolderPermissions(string filename)
{
var fs = File.GetAccessControl(filename);
fs.SetAccessRuleProtection(false, false);
File.SetAccessControl(filename, fs);
}
public virtual ulong FreeDiskSpace(DirectoryInfo directoryInfo)
{
ulong freeBytesAvailable;
ulong totalNumberOfBytes;
ulong totalNumberOfFreeBytes;
bool success = GetDiskFreeSpaceEx(directoryInfo.FullName, out freeBytesAvailable, out totalNumberOfBytes,
out totalNumberOfFreeBytes);
if (!success)
throw new System.ComponentModel.Win32Exception();
return freeBytesAvailable;
}
}
}
}

View File

@ -17,11 +17,12 @@ namespace NzbDrone.Common
private const string NZBDRONE_DB_FILE = "nzbdrone.sdf";
private const string LOG_DB_FILE = "log.sdf";
public const string UPDATE_SANDBOX_FOLDER_NAME = "nzbdrone_update";
private const string UPDATE_SANDBOX_FOLDER_NAME = "nzbdrone_update";
private const string UPDATE_BACKUP_FOLDER_NAME = "nzbdrone_backup";
private readonly string _applicationPath;
public PathProvider(EnviromentProvider enviromentProvider)
{
_applicationPath = enviromentProvider.ApplicationPath;
@ -29,7 +30,7 @@ namespace NzbDrone.Common
public PathProvider()
{
}
public virtual String LogPath
@ -103,9 +104,19 @@ namespace NzbDrone.Common
get { return Path.Combine(AppData, "Cache"); }
}
public string UpdateSandboxFolder
public virtual string UpdateSandboxFolder
{
get { return Path.Combine(SystemTemp, UPDATE_SANDBOX_FOLDER_NAME); }
}
public virtual string UpdatePackageFolder
{
get { return Path.Combine(UPDATE_SANDBOX_FOLDER_NAME, "NzbDrone"); }
}
public virtual string UpdateBackUpFolder
{
get { return Path.Combine(UpdateSandboxFolder, UPDATE_BACKUP_FOLDER_NAME); }
}
}
}

View File

@ -22,6 +22,16 @@ namespace NzbDrone.Common
s => String.Equals(s.ServiceName, name, StringComparison.InvariantCultureIgnoreCase));
}
public virtual bool IsServiceRunning(string name)
{
Logger.Debug("Checking if '{0}' service is running", name);
var service = ServiceController.GetServices()
.SingleOrDefault(s => String.Equals(s.ServiceName, name, StringComparison.InvariantCultureIgnoreCase));
return service != null && service.Status == ServiceControllerStatus.Running;
}
public virtual void Install(string serviceName)
{

View File

@ -11,7 +11,6 @@ using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Providers.Jobs;
using NzbDrone.Core.Repository;
using NzbDrone.Core.Test.Framework;
using DiskProvider = NzbDrone.Core.Providers.Core.DiskProvider;
namespace NzbDrone.Core.Test.JobTests
{

View File

@ -12,10 +12,10 @@ namespace NzbDrone.Core.Test.ProviderTests.DiskProviderTests
[Test]
public void Should_extract_to_correct_folder()
{
var diskProvider = new DiskProvider();
var archiveProvider = new ArchiveProvider();
var destination = Path.Combine(TempFolder, "destination");
diskProvider.ExtractArchive(GetTestFilePath("TestArchive.zip"), destination);
archiveProvider.ExtractArchive(GetTestFilePath("TestArchive.zip"), destination);
var destinationFolder = new DirectoryInfo(destination);

View File

@ -7,6 +7,7 @@ using AutoMoq;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Common;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Test.Framework;

View File

@ -4,6 +4,7 @@ using AutoMoq;
using FizzWare.NBuilder;
using Moq;
using NUnit.Framework;
using NzbDrone.Common;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Repository;

View File

@ -5,6 +5,7 @@ using FizzWare.NBuilder;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Common;
using NzbDrone.Core.Model;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Core;

View File

@ -6,6 +6,7 @@ using FizzWare.NBuilder;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Common;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Repository;

View File

@ -7,6 +7,7 @@ using AutoMoq;
using FizzWare.NBuilder;
using Moq;
using NUnit.Framework;
using NzbDrone.Common;
using NzbDrone.Core.Model;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Core;

View File

@ -6,6 +6,7 @@ using AutoMoq;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Common;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Repository;

View File

@ -1,29 +1,34 @@
using System;
using System.IO;
using AutoMoq;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Common;
using NzbDrone.Core.Model;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Test.Framework;
using DiskProvider = NzbDrone.Core.Providers.Core.DiskProvider;
namespace NzbDrone.Core.Test.ProviderTests.UpdateProviderTests
{
[TestFixture]
internal class PreformUpdateFixture : TestBase
{
private AutoMoqer _mocker = null;
private string SandBoxPath;
[SetUp]
public void setup()
{
_mocker = new AutoMoqer(MockBehavior.Strict);
_mocker.GetMock<PathProvider>()
.SetupGet(c => c.SystemTemp).Returns(TempFolder);
WithStrictMocker();
Mocker.GetMock<PathProvider>()
.SetupGet(c => c.UpdateSandboxFolder).Returns(Path.Combine(TempFolder, "NzbDrone_update"));
SandBoxPath = Mocker.GetMock<PathProvider>().Object.UpdateSandboxFolder;
Mocker.GetMock<PathProvider>()
.SetupGet(c => c.UpdatePackageFolder).Returns(Path.Combine(SandBoxPath, "NzbDrone"));
}
@ -38,21 +43,20 @@ namespace NzbDrone.Core.Test.ProviderTests.UpdateProviderTests
Version = new Version("0.6.0.2031")
};
_mocker.GetMock<HttpProvider>().Setup(
c => c.DownloadFile(updatePackage.Url, Path.Combine(TempFolder, PathProvider.UPDATE_SANDBOX_FOLDER_NAME, updatePackage.FileName)));
Mocker.GetMock<HttpProvider>().Setup(
c => c.DownloadFile(updatePackage.Url, Path.Combine(SandBoxPath, updatePackage.FileName)));
_mocker.GetMock<DiskProvider>().Setup(
c => c.ExtractArchive(Path.Combine(TempFolder, PathProvider.UPDATE_SANDBOX_FOLDER_NAME, updatePackage.FileName),
Path.Combine(TempFolder, PathProvider.UPDATE_SANDBOX_FOLDER_NAME)));
Mocker.GetMock<ArchiveProvider>().Setup(
c => c.ExtractArchive(Path.Combine(SandBoxPath, updatePackage.FileName), SandBoxPath));
_mocker.Resolve<UpdateProvider>().PreformUpdate(updatePackage);
Mocker.Resolve<UpdateProvider>().StartUpgrade(updatePackage);
}
[Test]
public void Should_download_and_extract_to_temp_folder()
{
var updateSubFolder = new DirectoryInfo(Path.Combine(TempFolder, PathProvider.UPDATE_SANDBOX_FOLDER_NAME));
var updateSubFolder = new DirectoryInfo(SandBoxPath);
var updatePackage = new UpdatePackage
{
@ -65,9 +69,10 @@ namespace NzbDrone.Core.Test.ProviderTests.UpdateProviderTests
//Act
updateSubFolder.Exists.Should().BeFalse();
_mocker.Resolve<HttpProvider>();
_mocker.Resolve<DiskProvider>();
_mocker.Resolve<UpdateProvider>().PreformUpdate(updatePackage);
Mocker.Resolve<HttpProvider>();
Mocker.Resolve<DiskProvider>();
Mocker.Resolve<ArchiveProvider>();
Mocker.Resolve<UpdateProvider>().StartUpgrade(updatePackage);
updateSubFolder.Refresh();
//Assert

View File

@ -1,122 +1,25 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Linq;
using Ionic.Zip;
using NLog;
namespace NzbDrone.Core.Providers.Core
{
public class DiskProvider
public class ArchiveProvider
{
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetDiskFreeSpaceEx(string lpDirectoryName,
out ulong lpFreeBytesAvailable,
out ulong lpTotalNumberOfBytes,
out ulong lpTotalNumberOfFreeBytes);
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public virtual bool FolderExists(string path)
{
return Directory.Exists(path);
}
public virtual bool FileExists(string path)
{
return File.Exists(path);
}
public virtual string[] GetDirectories(string path)
{
return Directory.GetDirectories(path);
}
public virtual string[] GetFiles(string path, SearchOption searchOption)
{
return Directory.GetFiles(path, "*.*", searchOption);
}
public virtual long GetDirectorySize(string path)
{
return GetFiles(path, SearchOption.AllDirectories).Sum(e => new FileInfo(e).Length);
}
public virtual long GetSize(string path)
{
var fi = new FileInfo(path);
return fi.Length;
//return new FileInfo(path).Length;
}
public virtual String CreateDirectory(string path)
{
return Directory.CreateDirectory(path).FullName;
}
public virtual void DeleteFile(string path)
{
File.Delete(path);
}
public virtual void MoveFile(string sourcePath, string destinationPath)
{
File.Move(sourcePath, destinationPath);
}
public virtual void DeleteFolder(string path, bool recursive)
{
Directory.Delete(path, recursive);
}
public virtual DateTime DirectoryDateCreated(string path)
{
return Directory.GetCreationTime(path);
}
public virtual IEnumerable<FileInfo> GetFileInfos(string path, string pattern, SearchOption searchOption)
{
return new DirectoryInfo(path).GetFiles(pattern, searchOption);
}
public virtual void MoveDirectory(string source, string destination)
{
Directory.Move(source, destination);
}
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
public virtual void ExtractArchive(string compressedFile, string destination)
{
Logger.Trace("Extracting archive [{0}] to [{1}]", compressedFile, destination);
logger.Trace("Extracting archive [{0}] to [{1}]", compressedFile, destination);
using (ZipFile zipFile = ZipFile.Read(compressedFile))
{
zipFile.ExtractAll(destination);
}
Logger.Trace("Extraction complete.");
logger.Trace("Extraction complete.");
}
public virtual void InheritFolderPermissions(string filename)
{
var fs = File.GetAccessControl(filename);
fs.SetAccessRuleProtection(false, false);
File.SetAccessControl(filename, fs);
}
public virtual ulong FreeDiskSpace(DirectoryInfo directoryInfo)
{
ulong freeBytesAvailable;
ulong totalNumberOfBytes;
ulong totalNumberOfFreeBytes;
bool success = GetDiskFreeSpaceEx(directoryInfo.FullName, out freeBytesAvailable, out totalNumberOfBytes,
out totalNumberOfFreeBytes);
if (!success)
throw new System.ComponentModel.Win32Exception();
return freeBytesAvailable;
}
}
}

View File

@ -4,6 +4,7 @@ using System.IO;
using System.Linq;
using Ninject;
using NLog;
using NzbDrone.Common;
using NzbDrone.Core.Model;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Repository;

View File

@ -8,7 +8,6 @@ using NzbDrone.Common;
using NzbDrone.Core.Model.Notification;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Repository;
using DiskProvider = NzbDrone.Core.Providers.Core.DiskProvider;
namespace NzbDrone.Core.Providers.Jobs
{

View File

@ -1,6 +1,7 @@
using System;
using NLog;
using Ninject;
using NzbDrone.Common;
using NzbDrone.Core.Model.Notification;
using NzbDrone.Core.Providers.Core;

View File

@ -3,6 +3,7 @@ using System.IO;
using System.Text.RegularExpressions;
using NLog;
using Ninject;
using NzbDrone.Common;
using NzbDrone.Core.Model;
using NzbDrone.Core.Providers.Core;

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using Ninject;
using NLog;
using NzbDrone.Common;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Repository;
using PetaPoco;

View File

@ -2,14 +2,13 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using NLog;
using Ninject;
using NzbDrone.Common;
using NzbDrone.Core.Model;
using NzbDrone.Core.Providers.Core;
using DiskProvider = NzbDrone.Core.Providers.Core.DiskProvider;
namespace NzbDrone.Core.Providers
{
@ -20,6 +19,7 @@ namespace NzbDrone.Core.Providers
private readonly EnviromentProvider _enviromentProvider;
private readonly PathProvider _pathProvider;
private readonly DiskProvider _diskProvider;
private readonly ArchiveProvider _archiveProvider;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private static readonly Regex ParseRegex = new Regex(@"(?:\>)(?<filename>NzbDrone.+?(?<version>\d+\.\d+\.\d+\.\d+).+?)(?:\<\/A\>)", RegexOptions.IgnoreCase);
@ -28,13 +28,14 @@ namespace NzbDrone.Core.Providers
[Inject]
public UpdateProvider(HttpProvider httpProvider, ConfigProvider configProvider, EnviromentProvider enviromentProvider,
PathProvider pathProvider, DiskProvider diskProvider)
PathProvider pathProvider, DiskProvider diskProvider, ArchiveProvider archiveProvider)
{
_httpProvider = httpProvider;
_configProvider = configProvider;
_enviromentProvider = enviromentProvider;
_pathProvider = pathProvider;
_diskProvider = diskProvider;
_archiveProvider = archiveProvider;
}
public UpdateProvider()
@ -74,7 +75,7 @@ namespace NzbDrone.Core.Providers
return null;
}
public virtual void PreformUpdate(UpdatePackage updatePackage)
public virtual void StartUpgrade(UpdatePackage updatePackage)
{
var packageDestination = Path.Combine(_pathProvider.UpdateSandboxFolder, updatePackage.FileName);
@ -83,7 +84,7 @@ namespace NzbDrone.Core.Providers
Logger.Info("Download completed for update package from [{0}]", updatePackage.FileName);
Logger.Info("Extracting Update package");
_diskProvider.ExtractArchive(packageDestination, _pathProvider.UpdateSandboxFolder);
_archiveProvider.ExtractArchive(packageDestination, _pathProvider.UpdateSandboxFolder);
Logger.Info("Update package extracted successfully");
}

View File

@ -1,4 +1,5 @@
using AutoMoq;
using System.IO;
using AutoMoq;
using FizzWare.NBuilder;
using Moq;
using NUnit.Framework;
@ -13,21 +14,47 @@ namespace NzbDrone.Update.Test
{
AutoMoqer mocker = new AutoMoqer();
private const string UPDATE_FOLDER = @"C:\Temp\NzbDrone_update\NzbDrone";
private const string BACKUP_FOLDER = @"C:\Temp\NzbDrone_update\NzbDrone_Backup";
private const string TARGET_FOLDER = @"C:\NzbDrone\";
Mock<PathProvider> _pathProvider = null;
[SetUp]
public void Setup()
{
mocker = new AutoMoqer();
_pathProvider = mocker.GetMock<PathProvider>();
_pathProvider.SetupGet(c => c.UpdateBackUpFolder).Returns(BACKUP_FOLDER);
_pathProvider.SetupGet(c => c.UpdatePackageFolder).Returns(UPDATE_FOLDER);
mocker.GetMock<DiskProvider>()
.Setup(c => c.FolderExists(UPDATE_FOLDER))
.Returns(true);
mocker.GetMock<DiskProvider>()
.Setup(c => c.FolderExists(TARGET_FOLDER))
.Returns(true);
}
public void WithInstalledService()
{
mocker.GetMock<ServiceProvider>()
.Setup(c => c.ServiceExist(ServiceProvider.NZBDRONE_SERVICE_NAME))
.Returns(true);
}
[Test]
public void should_stop_nzbdrone_service_if_installed()
{
mocker.GetMock<ServiceProvider>()
.Setup(c => c.ServiceExist(ServiceProvider.NZBDRONE_SERVICE_NAME))
.Returns(true);
WithInstalledService();
//Act
mocker.Resolve<UpdateProvider>().Start(null);
mocker.Resolve<UpdateProvider>().Start(TARGET_FOLDER);
//Assert
mocker.GetMock<ServiceProvider>().Verify(c => c.Stop(ServiceProvider.NZBDRONE_SERVICE_NAME), Times.Once());
@ -44,12 +71,89 @@ namespace NzbDrone.Update.Test
.Returns(proccesses);
//Act
mocker.Resolve<UpdateProvider>().Start(null);
mocker.Resolve<UpdateProvider>().Start(TARGET_FOLDER);
//Assert
mocker.GetMock<ProcessProvider>().Verify(c => c.Kill(proccesses[0].Id), Times.Once());
mocker.GetMock<ProcessProvider>().Verify(c => c.Kill(proccesses[1].Id), Times.Once());
mocker.VerifyAllMocks();
}
[Test]
public void should_create_backup_of_current_installation()
{
var diskprovider = mocker.GetMock<DiskProvider>()
.Setup(c => c.CopyDirectory(TARGET_FOLDER, BACKUP_FOLDER));
mocker.Resolve<UpdateProvider>().Start(TARGET_FOLDER);
mocker.VerifyAllMocks();
}
[Test]
public void should_copy_update_package_to_target()
{
var diskprovider = mocker.GetMock<DiskProvider>()
.Setup(c => c.CopyDirectory(UPDATE_FOLDER, TARGET_FOLDER));
mocker.Resolve<UpdateProvider>().Start(TARGET_FOLDER);
mocker.VerifyAllMocks();
}
[Test]
public void should_restore_if_update_fails()
{
var diskprovider = mocker.GetMock<DiskProvider>();
diskprovider.Setup(c => c.CopyDirectory(BACKUP_FOLDER, TARGET_FOLDER));
diskprovider.Setup(c => c.CopyDirectory(UPDATE_FOLDER, TARGET_FOLDER)).Throws(new IOException());
mocker.Resolve<UpdateProvider>().Start(TARGET_FOLDER);
mocker.VerifyAllMocks();
}
[Test]
public void should_restart_service_if_service_was_running()
{
WithInstalledService();
var serviceProvider = mocker.GetMock<ServiceProvider>();
serviceProvider.Setup(c => c.IsServiceRunning(ServiceProvider.NZBDRONE_SERVICE_NAME)).Returns(true);
//Act
mocker.Resolve<UpdateProvider>().Start(TARGET_FOLDER);
//Assert
serviceProvider
.Verify(c => c.Start(ServiceProvider.NZBDRONE_SERVICE_NAME), Times.Once());
mocker.VerifyAllMocks();
}
[Test]
public void should_not_restart_service_if_service_was_not_running()
{
WithInstalledService();
var serviceProvider = mocker.GetMock<ServiceProvider>();
serviceProvider.Setup(c => c.IsServiceRunning(ServiceProvider.NZBDRONE_SERVICE_NAME))
.Returns(false);
//Act
mocker.Resolve<UpdateProvider>().Start(TARGET_FOLDER);
//Assert
mocker.GetMock<ProcessProvider>()
.Verify(c => c.Start(TARGET_FOLDER + "nzbdrone.exe"), Times.Once());
serviceProvider
.Verify(c => c.Start(It.IsAny<string>()), Times.Never());
mocker.VerifyAllMocks();
}
}
}

View File

@ -28,25 +28,25 @@ namespace NzbDrone.Update.Test
[TestCase(null)]
[TestCase("")]
[TestCase(" ")]
public void verify_should_throw_target_folder_is_blank(string target)
public void update_should_throw_target_folder_is_blank(string target)
{
Assert.Throws<ArgumentException>(() => mocker.Resolve<UpdateProvider>().Verify(target))
Assert.Throws<ArgumentException>(() => mocker.Resolve<UpdateProvider>().Start(target))
.Message.Should().StartWith("Target folder can not be null or empty");
}
[Test]
public void verify_should_throw_if_target_folder_doesnt_exist()
public void update_should_throw_if_target_folder_doesnt_exist()
{
string targetFolder = "c:\\NzbDrone\\";
Assert.Throws<DirectoryNotFoundException>(() => mocker.Resolve<UpdateProvider>().Verify(targetFolder))
Assert.Throws<DirectoryNotFoundException>(() => mocker.Resolve<UpdateProvider>().Start(targetFolder))
.Message.Should().StartWith("Target folder doesn't exist");
}
[Test]
public void verify_should_throw_if_update_folder_doesnt_exist()
public void update_should_throw_if_update_folder_doesnt_exist()
{
const string sandboxFolder = @"C:\Temp\NzbDrone_update\nzbdrone_update";
const string sandboxFolder = @"C:\Temp\NzbDrone_update\nzbdrone";
const string targetFolder = "c:\\NzbDrone\\";
mocker.GetMock<DiskProvider>()
@ -57,22 +57,8 @@ namespace NzbDrone.Update.Test
.Setup(c => c.FolderExists(sandboxFolder))
.Returns(false);
Assert.Throws<DirectoryNotFoundException>(() => mocker.Resolve<UpdateProvider>().Verify(targetFolder))
Assert.Throws<DirectoryNotFoundException>(() => mocker.Resolve<UpdateProvider>().Start(targetFolder))
.Message.Should().StartWith("Update folder doesn't exist");
}
[Test]
public void verify_should_pass_if_update_folder_and_target_folder_both_exist()
{
const string targetFolder = "c:\\NzbDrone\\";
mocker.GetMock<DiskProvider>()
.Setup(c => c.FolderExists(It.IsAny<string>()))
.Returns(true);
mocker.Resolve<UpdateProvider>().Verify(targetFolder);
mocker.VerifyAllMocks();
}
}
}

View File

@ -12,40 +12,47 @@ namespace NzbDrone.Update.Providers
private readonly EnviromentProvider _enviromentProvider;
private readonly ServiceProvider _serviceProvider;
private readonly ProcessProvider _processProvider;
private readonly PathProvider _pathProvider;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public UpdateProvider(DiskProvider diskProvider, EnviromentProvider enviromentProvider,
ServiceProvider serviceProvider, ProcessProvider processProvider)
ServiceProvider serviceProvider, ProcessProvider processProvider, PathProvider pathProvider)
{
_diskProvider = diskProvider;
_enviromentProvider = enviromentProvider;
_serviceProvider = serviceProvider;
_processProvider = processProvider;
_pathProvider = pathProvider;
}
public void Verify(string targetFolder)
private void Verify(string installationFolder)
{
Logger.Info("Verifying requirements before update...");
if (String.IsNullOrWhiteSpace(targetFolder))
if (String.IsNullOrWhiteSpace(installationFolder))
throw new ArgumentException("Target folder can not be null or empty");
if (!_diskProvider.FolderExists(targetFolder))
throw new DirectoryNotFoundException("Target folder doesn't exist" + targetFolder);
var sandboxFolder = Path.Combine(_enviromentProvider.StartUpPath, "nzbdrone_update");
if (!_diskProvider.FolderExists(installationFolder))
throw new DirectoryNotFoundException("Target folder doesn't exist" + installationFolder);
Logger.Info("Verifying Update Folder");
if (!_diskProvider.FolderExists(sandboxFolder))
throw new DirectoryNotFoundException("Update folder doesn't exist" + sandboxFolder);
if (!_diskProvider.FolderExists(_pathProvider.UpdatePackageFolder))
throw new DirectoryNotFoundException("Update folder doesn't exist" + _pathProvider.UpdateSandboxFolder);
}
public void Start(string installationFolder)
public void Start(string targetFolder)
{
Verify(targetFolder);
bool isService = false;
Logger.Info("Stopping all running services");
if (_serviceProvider.ServiceExist(ServiceProvider.NZBDRONE_SERVICE_NAME))
{
if (_serviceProvider.IsServiceRunning(ServiceProvider.NZBDRONE_SERVICE_NAME))
{
isService = true;
}
_serviceProvider.Stop(ServiceProvider.NZBDRONE_SERVICE_NAME);
}
@ -56,17 +63,44 @@ namespace NzbDrone.Update.Providers
_processProvider.Kill(processInfo.Id);
}
Logger.Info("Creating backup of existing installation");
_diskProvider.CopyDirectory(targetFolder, _pathProvider.UpdateBackUpFolder);
//Create backup of current folder
//Copy update folder on top of the existing folder
Logger.Info("Copying update package to target");
//Happy: Cleanup
//Happy: Start Service, Process?
try
{
_diskProvider.CopyDirectory(_pathProvider.UpdatePackageFolder, targetFolder);
}
catch (Exception e)
{
RollBack(targetFolder);
Logger.Fatal("Failed to copy upgrade package to target folder.", e);
}
finally
{
StartNzbDrone(isService, targetFolder);
}
}
//Sad: delete fucked up folder
//Sad: restore backup
//Sad: start service, process
private void RollBack(string targetFolder)
{
Logger.Info("Attempting to rollback upgrade");
_diskProvider.CopyDirectory(_pathProvider.UpdateBackUpFolder, targetFolder);
}
private void StartNzbDrone(bool isService, string targetFolder)
{
if (isService)
{
_serviceProvider.Start(ServiceProvider.NZBDRONE_SERVICE_NAME);
}
else
{
_processProvider.Start(Path.Combine(targetFolder, "nzbdrone.exe"));
}
}
}
}

View File

@ -4,6 +4,7 @@ using System.IO;
using System.Linq;
using System.Web.Mvc;
using NLog;
using NzbDrone.Common;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Providers.Jobs;

View File

@ -1,9 +1,5 @@
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Helpers;
using System.Web.Mvc;
using NzbDrone.Core.Providers.Core;
using System.Web.Mvc;
using NzbDrone.Common;
namespace NzbDrone.Web.Controllers
{

View File

@ -3,8 +3,8 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web.Mvc;
using NzbDrone.Common;
using NzbDrone.Core.Helpers;
using NzbDrone.Core.Model;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Providers.Core;
using NzbDrone.Core.Providers.Jobs;