feat: Add migration step to delete old repo directory

pull/201/head
Robert Dailey 11 months ago
parent b26cd3bd5a
commit 010c788e14

@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Added
- Migration step added to delete old `repo` directory. Run `recyclarr migrate` to use.
## [5.0.3] - 2023-06-25
### Fixed

@ -36,6 +36,7 @@ public class MigrateCommand : Command<MigrateCommand.CliSettings>
try
{
_migration.PerformAllMigrationSteps(settings.Debug);
_console.WriteLine("All migration steps completed");
}
catch (MigrationException e)
{

@ -62,6 +62,7 @@ public class SyncCommand : AsyncCommand<SyncCommand.CliSettings>
{
// Will throw if migration is required, otherwise just a warning is issued.
_migration.CheckNeededMigrations();
await _repoUpdater.Update();
return (int) await _syncProcessor.ProcessConfigs(settings);

@ -1,13 +0,0 @@
using Spectre.Console;
namespace Recyclarr.Cli.Migration;
public interface IMigrationStep
{
int Order { get; }
string Description { get; }
IReadOnlyCollection<string> Remediation { get; }
bool Required { get; }
bool CheckIfNeeded();
void Execute(IAnsiConsole? console);
}

@ -1,4 +1,5 @@
using Autofac;
using Recyclarr.Cli.Migration.Steps;
namespace Recyclarr.Cli.Migration;
@ -10,10 +11,8 @@ public class MigrationAutofacModule : Module
builder.RegisterType<MigrationExecutor>().As<IMigrationExecutor>();
// Migration Steps
builder.RegisterTypes
(
// Add migration steps here in order of execution
)
builder.RegisterAssemblyTypes(ThisAssembly)
.AssignableTo<IMigrationStep>()
.As<IMigrationStep>();
}
}

@ -1,3 +1,4 @@
using Recyclarr.Cli.Migration.Steps;
using Spectre.Console;
namespace Recyclarr.Cli.Migration;
@ -13,12 +14,10 @@ public class MigrationExecutor : IMigrationExecutor
_migrationSteps = migrationSteps.OrderBy(x => x.Order).ToList();
}
public void PerformAllMigrationSteps(bool withDiagnostics)
private void PerformMigrationStepsImpl(bool withDiagnostics, IEnumerable<IMigrationStep> migrationSteps)
{
_console.WriteLine("Performing migration steps...");
// ReSharper disable once ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator
foreach (var step in _migrationSteps)
foreach (var step in migrationSteps)
{
// Do not use LINQ to filter using CheckIfNeeded(). If it returns true, then 'Execute()' must be invoked to
// cause the necessary changes to happen. Those changes may be required in order for the *next* step's
@ -41,6 +40,11 @@ public class MigrationExecutor : IMigrationExecutor
}
}
public void PerformAllMigrationSteps(bool withDiagnostics)
{
PerformMigrationStepsImpl(withDiagnostics, _migrationSteps);
}
public void CheckNeededMigrations()
{
var neededMigrationSteps = _migrationSteps.Where(x => x.CheckIfNeeded()).ToList();

@ -0,0 +1,40 @@
using System.IO.Abstractions;
using JetBrains.Annotations;
using Recyclarr.Common.Extensions;
using Recyclarr.TrashLib.Startup;
using Spectre.Console;
namespace Recyclarr.Cli.Migration.Steps;
[UsedImplicitly]
public class DeleteRepoDirMigrationStep : IMigrationStep
{
private readonly IAppPaths _paths;
public DeleteRepoDirMigrationStep(IAppPaths paths)
{
_paths = paths;
}
public int Order => 1;
public string Description => "Delete old repo directory";
public IReadOnlyCollection<string> Remediation => new[]
{
$"Ensure Recyclarr has permission to recursively delete {RepoDir}",
$"Delete {RepoDir} manually if Recyclarr can't do it"
};
public bool Required => false;
private IDirectoryInfo RepoDir => _paths.AppDataDirectory.SubDir("repo");
public bool CheckIfNeeded()
{
return RepoDir.Exists;
}
public void Execute(IAnsiConsole? console)
{
RepoDir.RecursivelyDeleteReadOnly();
console?.WriteLine($"Deleted repo dir: {RepoDir.FullName}");
}
}

@ -0,0 +1,47 @@
using Spectre.Console;
namespace Recyclarr.Cli.Migration.Steps;
public interface IMigrationStep
{
/// <summary>
/// Determines the order in which this migration step will run.
/// </summary>
int Order { get; }
/// <summary>
/// A description printed to the user so that they understand the purpose of this migration step, and
/// what it does.
/// </summary>
string Description { get; }
/// <summary>
/// One or more strings that individually represent a distinct manual solution that a user can attempt
/// when this migration step fails.
/// </summary>
IReadOnlyCollection<string> Remediation { get; }
/// <summary>
/// Determines if this migration step is required. If so, it must be executed before the program may be
/// used normally.
/// </summary>
bool Required { get; }
/// <summary>
/// Run logic to determine if this migration step is necessary
/// </summary>
/// <returns>
/// Return true if this migration step is needed and should be run. False means the migration step is
/// not needed and Execute() will not be called.
/// </returns>
bool CheckIfNeeded();
/// <summary>
/// Execute the logic necessary for this migration step.
/// </summary>
/// <param name="console">
/// Use the console to print additional debug diagnostics. If this parameter is null, that means those
/// diagnostics should not be printed.
/// </param>
void Execute(IAnsiConsole? console);
}

@ -37,8 +37,4 @@
<ItemGroup>
<EmbeddedResource Include="config-template.yml" />
</ItemGroup>
<ItemGroup>
<Folder Include="Migration\Steps\" />
</ItemGroup>
</Project>

@ -95,4 +95,14 @@ public static class FileSystemExtensions
return configs.FirstOrDefault();
}
public static void RecursivelyDeleteReadOnly(this IDirectoryInfo dir)
{
foreach (var info in dir.GetFileSystemInfos("*", SearchOption.AllDirectories))
{
info.Attributes = FileAttributes.Normal;
}
dir.Delete(true);
}
}

@ -1,4 +1,5 @@
using Recyclarr.Cli.Migration;
using Recyclarr.Cli.Migration.Steps;
using Recyclarr.Cli.TestLibrary;
using Spectre.Console.Testing;

Loading…
Cancel
Save