feat: New migrate subcommand

Automatic migration no longer takes place. Instead, the user must run
`recyclarr migrate` to have those migration steps executed
automatically, or do it manually.
pull/76/head
Robert Dailey 2 years ago
parent bba4d2a08a
commit 276f59ae8c

@ -11,11 +11,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- New `--app-data` option for overriding the location of the application data directory.
- New `migrate` subcommand which may be used to perform migration steps manually.
### Changed
- The default location for the default YAML file (`recyclarr.yml`) has been changed to the
[application data directory](appdata). This is the same location of the `settings.yml` file.
- Automatic migration has been removed. Instead, the `migrate` subcommand should be used.
### Deprecated

@ -0,0 +1,18 @@
using Recyclarr.Migration;
namespace Recyclarr.Command.Initialization.Init;
internal class CheckMigrationNeeded : IServiceInitializer
{
private readonly IMigrationExecutor _migration;
public CheckMigrationNeeded(IMigrationExecutor migration)
{
_migration = migration;
}
public void Initialize(ServiceCommand cmd)
{
_migration.CheckNeededMigrations();
}
}

@ -16,7 +16,7 @@ public class InitializationAutofacModule : Module
builder.RegisterTypes(
typeof(InitializeAppDataPath),
typeof(ServiceInitializer),
typeof(ServicePreInitializer))
typeof(CheckMigrationNeeded))
.As<IServiceInitializer>()
.OrderByRegistration();

@ -1,24 +1,28 @@
using System.Text;
using CliFx;
using CliFx.Attributes;
using CliFx.Exceptions;
using CliFx.Infrastructure;
using JetBrains.Annotations;
using Recyclarr.Migration;
namespace Recyclarr.Command.Initialization.Init;
namespace Recyclarr.Command;
internal class ServicePreInitializer : IServiceInitializer
[Command("migrate", Description = "Perform any migration steps that may be needed between versions")]
[UsedImplicitly]
public class MigrateCommand : ICommand
{
private readonly IMigrationExecutor _migration;
public ServicePreInitializer(IMigrationExecutor migration)
public MigrateCommand(IMigrationExecutor migration)
{
_migration = migration;
}
public void Initialize(ServiceCommand cmd)
public ValueTask ExecuteAsync(IConsole console)
{
// Migrations are performed before we process command line arguments because we cannot instantiate any service
// objects via the DI container before migration logic is performed. This is due to the fact that migration
// steps may alter important files and directories which those services may depend on.
PerformMigrations();
return ValueTask.CompletedTask;
}
private void PerformMigrations()

@ -3,4 +3,5 @@ namespace Recyclarr.Migration;
public interface IMigrationExecutor
{
void PerformAllMigrationSteps();
void CheckNeededMigrations();
}

@ -5,6 +5,7 @@ public interface IMigrationStep
int Order { get; }
string Description { get; }
IReadOnlyCollection<string> Remediation { get; }
bool Required { get; }
bool CheckIfNeeded();
void Execute();
}

@ -1,3 +1,4 @@
using CliFx.Exceptions;
using CliFx.Infrastructure;
namespace Recyclarr.Migration;
@ -40,4 +41,30 @@ public class MigrationExecutor : IMigrationExecutor
_console.Output.WriteLine($"Migrate: {step.Description}");
}
}
public void CheckNeededMigrations()
{
var neededMigrationSteps = _migrationSteps.Where(x => x.CheckIfNeeded()).ToList();
if (neededMigrationSteps.Count == 0)
{
return;
}
var wereAnyRequired = false;
foreach (var step in neededMigrationSteps)
{
var requiredText = step.Required ? "Required" : "Not Required";
_console.Output.WriteLine($"Migration Needed ({requiredText}): {step.Description}");
wereAnyRequired |= step.Required;
}
_console.Output.WriteLine(
"\nRun the `migrate` subcommand to perform the above migration steps automatically\n");
if (wereAnyRequired)
{
throw new CommandException("Some migrations above are REQUIRED. Application will now exit.");
}
}
}

@ -3,9 +3,6 @@ using JetBrains.Annotations;
namespace Recyclarr.Migration.Steps;
/// <summary>
/// Rename `trash.yml` to `recyclarr.yml`.
/// </summary>
/// <remarks>
/// Implemented on 4/30/2022.
/// </remarks>
@ -24,6 +21,7 @@ public class MigrateTrashUpdaterAppDataDir : IMigrationStep
public int Order => 20;
public string Description { get; }
public IReadOnlyCollection<string> Remediation { get; }
public bool Required => true;
public MigrateTrashUpdaterAppDataDir(IFileSystem fileSystem)
{

@ -3,9 +3,6 @@ using JetBrains.Annotations;
namespace Recyclarr.Migration.Steps;
/// <summary>
/// Rename `trash.yml` to `recyclarr.yml`.
/// </summary>
/// <remarks>
/// Implemented on 4/30/2022.
/// </remarks>
@ -21,6 +18,7 @@ public class MigrateTrashYml : IMigrationStep
public int Order => 10;
public string Description { get; }
public IReadOnlyCollection<string> Remediation { get; }
public bool Required => true;
public MigrateTrashYml(IFileSystem fileSystem)
{
@ -32,7 +30,7 @@ public class MigrateTrashYml : IMigrationStep
$"Ensure Recyclarr has permission to create {_newConfigPath}"
};
Description = $"Migration from `{_oldConfigPath}` to `{_newConfigPath}`";
Description = $"Rename default YAML config from `{_oldConfigPath}` to `{_newConfigPath}`";
}
public bool CheckIfNeeded() => _fileSystem.File.Exists(_oldConfigPath);

Loading…
Cancel
Save