feat!: Restructure repository settings

pull/201/head
Robert Dailey 1 year ago
parent b8ac93a464
commit da35eef1ed

@ -17,7 +17,8 @@ changes you may need to make.
- API Key is now sent via the `X-Api-Key` header instead of the `apikey` query parameter. This
lessens the need to redact information in the console.
- **BREAKING**: `replace_existing_custom_formats` now defaults to `true`
- **BREAKING**: `replace_existing_custom_formats` now defaults to `true`.
- **BREAKING**: Restructured repository settings.
### Removed

@ -6,31 +6,18 @@
"description": "Optional settings to control the behavior of Recyclarr",
"additionalProperties": false,
"properties": {
"repository": {
"repositories": {
"type": "object",
"additionalProperties": false,
"title": "Settings for the git repo",
"description": "",
"title": "Settings for any local git clones that Recyclarr manages",
"properties": {
"clone_url": {
"type": "string",
"format": "uri",
"title": "Clone URL to the trash guides git repository",
"description": "A URL compatible with `git clone` that is used to clone the Trash Guides repository. This setting exists for enthusiasts that may want to instead have Recyclarr pull data from a fork instead of the official repository."
"trash_guide": {
"$ref": "#/$defs/repository",
"title": "Settings for the Trash Guides GitHub repository"
},
"branch": {
"type": "string",
"title": "The name of a branch to check out in the repository"
},
"sha1": {
"type": "string",
"title": "A SHA1 (commit hash) in Git to use",
"description": "If specified, it overrides the `branch` setting. This SHA1 is passed to `git reset --hard` to force your local clone to this specific revision in the repository. If not specified, only the `branch` controls what revision is used in the repo."
},
"git_path": {
"type": "string",
"title": "Provide an explicit path to your git executable",
"description": "Note that this is a path to the actual executable itself and not a directory path. If this setting is not specified, Recyclarr will attempt to find git via your PATH environment variable."
"config_templates": {
"$ref": "#/$defs/repository",
"title": "Settings for the Recyclarr Config Templates GitHub repository"
}
}
},
@ -54,5 +41,33 @@
}
}
}
},
"$defs": {
"repository": {
"type": "object",
"additionalProperties": false,
"properties": {
"clone_url": {
"type": "string",
"format": "uri",
"title": "Clone URL to the trash guides git repository",
"description": "A URL compatible with `git clone` that is used to clone the Trash Guides repository. This setting exists for enthusiasts that may want to instead have Recyclarr pull data from a fork instead of the official repository."
},
"branch": {
"type": "string",
"title": "The name of a branch to check out in the repository"
},
"sha1": {
"type": "string",
"title": "A SHA1 (commit hash) in Git to use",
"description": "If specified, it overrides the `branch` setting. This SHA1 is passed to `git reset --hard` to force your local clone to this specific revision in the repository. If not specified, only the `branch` controls what revision is used in the repo."
},
"git_path": {
"type": "string",
"title": "Provide an explicit path to your git executable",
"description": "Note that this is a path to the actual executable itself and not a directory path. If this setting is not specified, Recyclarr will attempt to find git via your PATH environment variable."
}
}
}
}
}

@ -15,14 +15,15 @@ public class ServiceCompatibilityIntegrationTest : CliIntegrationFixture
// For this test, it doesn't really matter if the YAML data matches what SettingsValue expects.
// This test only ensures that the data deserialized is from the actual correct file.
const string yamlData = @"
repository:
clone_url: http://the_url.com
repositories:
trash_guide:
clone_url: http://the_url.com
";
Fs.AddFile(Paths.SettingsPath.FullName, new MockFileData(yamlData));
var settings = sut.Settings;
settings.Repository.CloneUrl.Should().Be("http://the_url.com");
settings.Repositories.TrashGuide.CloneUrl.Should().Be("http://the_url.com");
}
}

@ -5,6 +5,7 @@ using Recyclarr.Cli.Console.Helpers;
using Recyclarr.Cli.Pipelines.CustomFormat.Guide;
using Recyclarr.TrashLib.Config;
using Recyclarr.TrashLib.Repo;
using Recyclarr.TrashLib.Settings;
using Spectre.Console.Cli;
#pragma warning disable CS8765
@ -17,6 +18,7 @@ internal class ListCustomFormatsCommand : AsyncCommand<ListCustomFormatsCommand.
{
private readonly CustomFormatDataLister _lister;
private readonly IRepoUpdater _repoUpdater;
private readonly ISettingsProvider _settings;
[UsedImplicitly]
[SuppressMessage("Design", "CA1034:Nested types should not be visible")]
@ -30,15 +32,17 @@ internal class ListCustomFormatsCommand : AsyncCommand<ListCustomFormatsCommand.
public ListCustomFormatsCommand(
CustomFormatDataLister lister,
IRepoUpdater repoUpdater)
IRepoUpdater repoUpdater,
ISettingsProvider settings)
{
_lister = lister;
_repoUpdater = repoUpdater;
_settings = settings;
}
public override async Task<int> ExecuteAsync(CommandContext context, CliSettings settings)
{
await _repoUpdater.UpdateRepo();
await _repoUpdater.UpdateRepo(_settings.Settings.Repositories.TrashGuide);
_lister.ListCustomFormats(settings.Service);
return 0;
}

@ -5,6 +5,7 @@ using Recyclarr.Cli.Console.Helpers;
using Recyclarr.Cli.Pipelines.QualitySize.Guide;
using Recyclarr.TrashLib.Config;
using Recyclarr.TrashLib.Repo;
using Recyclarr.TrashLib.Settings;
using Spectre.Console.Cli;
namespace Recyclarr.Cli.Console.Commands;
@ -16,6 +17,7 @@ internal class ListQualitiesCommand : AsyncCommand<ListQualitiesCommand.CliSetti
{
private readonly QualitySizeDataLister _lister;
private readonly IRepoUpdater _repoUpdater;
private readonly ISettingsProvider _settings;
[UsedImplicitly]
[SuppressMessage("Design", "CA1034:Nested types should not be visible")]
@ -27,15 +29,16 @@ internal class ListQualitiesCommand : AsyncCommand<ListQualitiesCommand.CliSetti
public SupportedServices Service { get; init; }
}
public ListQualitiesCommand(QualitySizeDataLister lister, IRepoUpdater repoUpdater)
public ListQualitiesCommand(QualitySizeDataLister lister, IRepoUpdater repoUpdater, ISettingsProvider settings)
{
_lister = lister;
_repoUpdater = repoUpdater;
_settings = settings;
}
public override async Task<int> ExecuteAsync(CommandContext context, CliSettings settings)
{
await _repoUpdater.UpdateRepo();
await _repoUpdater.UpdateRepo(_settings.Settings.Repositories.TrashGuide);
_lister.ListQualities(settings.Service);
return 0;
}

@ -3,6 +3,7 @@ using System.Diagnostics.CodeAnalysis;
using JetBrains.Annotations;
using Recyclarr.Cli.Pipelines.ReleaseProfile.Guide;
using Recyclarr.TrashLib.Repo;
using Recyclarr.TrashLib.Settings;
using Spectre.Console.Cli;
#pragma warning disable CS8765
@ -16,6 +17,7 @@ internal class ListReleaseProfilesCommand : AsyncCommand<ListReleaseProfilesComm
private readonly ILogger _log;
private readonly ReleaseProfileDataLister _lister;
private readonly IRepoUpdater _repoUpdater;
private readonly ISettingsProvider _settings;
[UsedImplicitly]
[SuppressMessage("Design", "CA1034:Nested types should not be visible")]
@ -32,18 +34,20 @@ internal class ListReleaseProfilesCommand : AsyncCommand<ListReleaseProfilesComm
public ListReleaseProfilesCommand(
ILogger log,
ReleaseProfileDataLister lister,
IRepoUpdater repoUpdater)
IRepoUpdater repoUpdater,
ISettingsProvider settings)
{
_log = log;
_lister = lister;
_repoUpdater = repoUpdater;
_settings = settings;
}
public override async Task<int> ExecuteAsync(CommandContext context, CliSettings settings)
{
try
{
await _repoUpdater.UpdateRepo();
await _repoUpdater.UpdateRepo(_settings.Settings.Repositories.TrashGuide);
if (settings.ListTerms is not null)
{

@ -8,6 +8,7 @@ using Recyclarr.Cli.Migration;
using Recyclarr.Cli.Processors;
using Recyclarr.TrashLib.Config;
using Recyclarr.TrashLib.Repo;
using Recyclarr.TrashLib.Settings;
using Spectre.Console.Cli;
namespace Recyclarr.Cli.Console.Commands;
@ -19,6 +20,7 @@ public class SyncCommand : AsyncCommand<SyncCommand.CliSettings>
private readonly IMigrationExecutor _migration;
private readonly IRepoUpdater _repoUpdater;
private readonly ISyncProcessor _syncProcessor;
private readonly ISettingsProvider _settings;
[UsedImplicitly]
[SuppressMessage("Design", "CA1034:Nested types should not be visible")]
@ -53,11 +55,13 @@ public class SyncCommand : AsyncCommand<SyncCommand.CliSettings>
public SyncCommand(
IMigrationExecutor migration,
IRepoUpdater repoUpdater,
ISyncProcessor syncProcessor)
ISyncProcessor syncProcessor,
ISettingsProvider settings)
{
_migration = migration;
_repoUpdater = repoUpdater;
_syncProcessor = syncProcessor;
_settings = settings;
}
[SuppressMessage("Design", "CA1031:Do not catch general exception types")]
@ -65,7 +69,7 @@ public class SyncCommand : AsyncCommand<SyncCommand.CliSettings>
{
// Will throw if migration is required, otherwise just a warning is issued.
_migration.CheckNeededMigrations();
await _repoUpdater.UpdateRepo();
await _repoUpdater.UpdateRepo(_settings.Settings.Repositories.TrashGuide);
return (int) await _syncProcessor.ProcessConfigs(settings);
}

@ -12,7 +12,10 @@ public class GitPathTest
[Frozen] ISettingsProvider settings,
GitPath sut)
{
settings.Settings.Returns(new SettingsValues {Repository = new TrashRepository {GitPath = null}});
settings.Settings.Returns(new SettingsValues
{
GitPath = null
});
var result = sut.Path;
@ -25,7 +28,10 @@ public class GitPathTest
GitPath sut)
{
var expectedPath = "/usr/local/bin/git";
settings.Settings.Returns(new SettingsValues {Repository = new TrashRepository {GitPath = expectedPath}});
settings.Settings.Returns(new SettingsValues
{
GitPath = expectedPath
});
var result = sut.Path;

@ -1,5 +1,6 @@
using Recyclarr.TrashLib.Config.Services;
using Recyclarr.TrashLib.Repo;
using Recyclarr.TrashLib.Settings;
using Spectre.Console;
namespace Recyclarr.TrashLib.Config.Listers;
@ -9,20 +10,23 @@ public class ConfigTemplateLister : IConfigLister
private readonly IAnsiConsole _console;
private readonly IConfigTemplateGuideService _guideService;
private readonly IRepoUpdater _repoUpdater;
private readonly ISettingsProvider _settings;
public ConfigTemplateLister(
IAnsiConsole console,
IConfigTemplateGuideService guideService,
IRepoUpdater repoUpdater)
IRepoUpdater repoUpdater,
ISettingsProvider settings)
{
_console = console;
_guideService = guideService;
_repoUpdater = repoUpdater;
_settings = settings;
}
public async Task List()
{
await _repoUpdater.UpdateRepo();
await _repoUpdater.UpdateRepo(_settings.Settings.Repositories.TrashGuide);
var data = _guideService.TemplateData;

@ -1,3 +1,4 @@
using Recyclarr.TrashLib.Settings;
using YamlDotNet.Core;
namespace Recyclarr.TrashLib.Config.Parsing.ErrorHandling;
@ -16,6 +17,16 @@ public static class ContextualMessages
"See: https://recyclarr.dev/wiki/upgrade-guide/v5.0/#reset-unmatched-scores";
}
if (e.Message.Contains(
"Property 'repository' not found on type " +
$"'{typeof(SettingsValues).FullName}'"))
{
return
"Usage of 'repository' setting is no " +
"longer supported. Use 'trash_guide' under 'repositories' instead." +
"See: https://recyclarr.dev/wiki/upgrade-guide/v5.0/#settings-repository-changes";
}
return null;
}
}

@ -1,9 +1,10 @@
using System.IO.Abstractions;
using Recyclarr.TrashLib.Settings;
namespace Recyclarr.TrashLib.Repo;
public interface IRepoUpdater
{
IDirectoryInfo RepoPath { get; }
Task UpdateRepo();
Task UpdateRepo(IRepositorySettings repoSettings);
}

@ -12,44 +12,40 @@ public class RepoUpdater : IRepoUpdater
private readonly IAppPaths _paths;
private readonly IGitRepositoryFactory _repositoryFactory;
private readonly IFileUtilities _fileUtils;
private readonly ISettingsProvider _settingsProvider;
public RepoUpdater(
ILogger log,
IAppPaths paths,
IGitRepositoryFactory repositoryFactory,
IFileUtilities fileUtils,
ISettingsProvider settingsProvider)
IFileUtilities fileUtils)
{
_log = log;
_paths = paths;
_repositoryFactory = repositoryFactory;
_fileUtils = fileUtils;
_settingsProvider = settingsProvider;
}
public IDirectoryInfo RepoPath => _paths.RepoDirectory;
public async Task UpdateRepo()
public async Task UpdateRepo(IRepositorySettings repoSettings)
{
// Retry only once if there's a failure. This gives us an opportunity to delete the git repository and start
// fresh.
try
{
await CheckoutAndUpdateRepo();
await CheckoutAndUpdateRepo(repoSettings);
}
catch (GitCmdException e)
{
_log.Debug(e, "Non-zero exit code {ExitCode} while executing Git command: {Error}", e.ExitCode, e.Error);
_log.Warning("Deleting local git repo and retrying git operation due to error...");
_fileUtils.DeleteReadOnlyDirectory(RepoPath.FullName);
await CheckoutAndUpdateRepo();
await CheckoutAndUpdateRepo(repoSettings);
}
}
private async Task CheckoutAndUpdateRepo()
private async Task CheckoutAndUpdateRepo(IRepositorySettings repoSettings)
{
var repoSettings = _settingsProvider.Settings.Repository;
var cloneUrl = repoSettings.CloneUrl;
var branch = repoSettings.Branch;

@ -12,5 +12,5 @@ public class GitPath : IGitPath
}
public static string Default => "git";
public string Path => _settings.Settings.Repository.GitPath ?? Default;
public string Path => _settings.Settings.GitPath ?? Default;
}

@ -0,0 +1,8 @@
namespace Recyclarr.TrashLib.Settings;
public interface IRepositorySettings
{
Uri CloneUrl { get; }
string Branch { get; }
string? Sha1 { get; }
}

@ -2,7 +2,7 @@ using JetBrains.Annotations;
namespace Recyclarr.TrashLib.Settings;
public record TrashRepository
public record TrashRepository : IRepositorySettings
{
public Uri CloneUrl { get; [UsedImplicitly] init; } = new("https://github.com/TRaSH-/Guides.git");
public string Branch { get; [UsedImplicitly] init; } = "master";
@ -15,9 +15,15 @@ public record LogJanitorSettings
public int MaxFiles { get; [UsedImplicitly] init; } = 20;
}
public record Repositories
{
public TrashRepository TrashGuide { get; [UsedImplicitly] init; } = new();
}
public record SettingsValues
{
public TrashRepository Repository { get; [UsedImplicitly] init; } = new();
public Repositories Repositories { get; [UsedImplicitly] init; } = new();
public bool EnableSslCertificateValidation { get; [UsedImplicitly] init; } = true;
public LogJanitorSettings LogJanitor { get; [UsedImplicitly] init; } = new();
public string? GitPath { get; [UsedImplicitly] init; }
}

Loading…
Cancel
Save