fix: Better error messages for non-existent config files

pull/201/head
Robert Dailey 11 months ago
parent ea09ddfb00
commit 7d757c0d5f

@ -13,6 +13,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `base_url` and `api_key` are now optional. These can be implicitly set via secrets that follow a - `base_url` and `api_key` are now optional. These can be implicitly set via secrets that follow a
naming convention. See the Secrets reference page on the wiki for details. naming convention. See the Secrets reference page on the wiki for details.
### Changed
- Better error messages for manually-specified, non-existent config files.
### Fixed ### Fixed
- Resolved error during exception message formatting that occurred in some cases (#192). - Resolved error during exception message formatting that occurred in some cases (#192).

@ -1,6 +1,5 @@
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.IO.Abstractions;
using JetBrains.Annotations; using JetBrains.Annotations;
using Recyclarr.Cli.Console.Helpers; using Recyclarr.Cli.Console.Helpers;
using Recyclarr.Cli.Console.Settings; using Recyclarr.Cli.Console.Settings;
@ -33,10 +32,9 @@ public class SyncCommand : AsyncCommand<SyncCommand.CliSettings>
[CommandOption("-c|--config")] [CommandOption("-c|--config")]
[Description("One or more YAML configuration files to load & use.")] [Description("One or more YAML configuration files to load & use.")]
[TypeConverter(typeof(FileInfoConverter))]
[UsedImplicitly(ImplicitUseKindFlags.Assign)] [UsedImplicitly(ImplicitUseKindFlags.Assign)]
public IFileInfo[] ConfigsOption { get; init; } = Array.Empty<IFileInfo>(); public string[] ConfigsOption { get; init; } = Array.Empty<string>();
public IReadOnlyCollection<IFileInfo> Configs => ConfigsOption; public IReadOnlyCollection<string> Configs => ConfigsOption;
[CommandOption("-p|--preview")] [CommandOption("-p|--preview")]
[Description("Perform a dry run: preview the results without syncing.")] [Description("Perform a dry run: preview the results without syncing.")]

@ -1,32 +0,0 @@
using System.ComponentModel;
using System.Globalization;
using System.IO.Abstractions;
namespace Recyclarr.Cli.Console.Helpers;
internal class FileInfoConverter : TypeConverter
{
private readonly IFileSystem _fs;
public FileInfoConverter(IFileSystem fs)
{
_fs = fs;
}
public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value)
{
// ReSharper disable once InvertIf
if (value is string path)
{
var info = _fs.FileInfo.New(path);
if (!info.Exists)
{
throw new FileNotFoundException("The file does not exist", path);
}
return info;
}
return null;
}
}

@ -1,4 +1,3 @@
using System.IO.Abstractions;
using Recyclarr.TrashLib.Config; using Recyclarr.TrashLib.Config;
namespace Recyclarr.Cli.Console.Settings; namespace Recyclarr.Cli.Console.Settings;
@ -6,7 +5,7 @@ namespace Recyclarr.Cli.Console.Settings;
public interface ISyncSettings public interface ISyncSettings
{ {
SupportedServices? Service { get; } SupportedServices? Service { get; }
IReadOnlyCollection<IFileInfo> Configs { get; } IReadOnlyCollection<string> Configs { get; }
bool Preview { get; } bool Preview { get; }
IReadOnlyCollection<string>? Instances { get; } IReadOnlyCollection<string>? Instances { get; }
} }

@ -1,4 +1,5 @@
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.IO.Abstractions;
using Flurl.Http; using Flurl.Http;
using Recyclarr.Cli.Console.Settings; using Recyclarr.Cli.Console.Settings;
using Recyclarr.TrashLib.Compatibility; using Recyclarr.TrashLib.Compatibility;
@ -20,6 +21,7 @@ public class SyncProcessor : ISyncProcessor
private readonly IConfigurationLoader _configLoader; private readonly IConfigurationLoader _configLoader;
private readonly SyncPipelineExecutor _pipelines; private readonly SyncPipelineExecutor _pipelines;
private readonly ServiceAgnosticCapabilityEnforcer _capabilityEnforcer; private readonly ServiceAgnosticCapabilityEnforcer _capabilityEnforcer;
private readonly IFileSystem _fs;
public SyncProcessor( public SyncProcessor(
IAnsiConsole console, IAnsiConsole console,
@ -27,7 +29,8 @@ public class SyncProcessor : ISyncProcessor
IConfigurationFinder configFinder, IConfigurationFinder configFinder,
IConfigurationLoader configLoader, IConfigurationLoader configLoader,
SyncPipelineExecutor pipelines, SyncPipelineExecutor pipelines,
ServiceAgnosticCapabilityEnforcer capabilityEnforcer) ServiceAgnosticCapabilityEnforcer capabilityEnforcer,
IFileSystem fs)
{ {
_console = console; _console = console;
_log = log; _log = log;
@ -35,6 +38,7 @@ public class SyncProcessor : ISyncProcessor
_configLoader = configLoader; _configLoader = configLoader;
_pipelines = pipelines; _pipelines = pipelines;
_capabilityEnforcer = capabilityEnforcer; _capabilityEnforcer = capabilityEnforcer;
_fs = fs;
} }
public async Task<ExitStatus> ProcessConfigs(ISyncSettings settings) public async Task<ExitStatus> ProcessConfigs(ISyncSettings settings)
@ -42,7 +46,22 @@ public class SyncProcessor : ISyncProcessor
bool failureDetected; bool failureDetected;
try try
{ {
var configs = _configLoader.LoadMany(_configFinder.GetConfigFiles(settings.Configs)); var configFiles = settings.Configs
.Select(x => _fs.FileInfo.New(x))
.ToLookup(x => x.Exists);
if (configFiles[false].Any())
{
foreach (var file in configFiles[false])
{
_log.Error("Manually-specified configuration file does not exist: {File}", file);
}
_log.Error("Exiting due to non-existent configuration files");
return ExitStatus.Failed;
}
var configs = _configLoader.LoadMany(_configFinder.GetConfigFiles(configFiles[true].ToList()));
LogInvalidInstances(settings.Instances, configs); LogInvalidInstances(settings.Instances, configs);
@ -93,6 +112,8 @@ public class SyncProcessor : ISyncProcessor
private void HandleException(Exception e) private void HandleException(Exception e)
{ {
_log.Debug(e, "Sync Processor Exception");
switch (e) switch (e)
{ {
case GitCmdException e2: case GitCmdException e2:
@ -105,8 +126,7 @@ public class SyncProcessor : ISyncProcessor
break; break;
default: default:
_log.Error(e, "Exception"); throw e;
break;
} }
} }

@ -38,7 +38,6 @@ internal static class Program
config.Settings.StrictParsing = true; config.Settings.StrictParsing = true;
config.SetApplicationName("recyclarr"); config.SetApplicationName("recyclarr");
// config.SetApplicationVersion("v1.2.3");
var interceptor = new CliInterceptor(logLevelSwitch, appDataPathProvider); var interceptor = new CliInterceptor(logLevelSwitch, appDataPathProvider);
interceptor.OnIntercepted.Subscribe(_ => OnAppInitialized()); interceptor.OnIntercepted.Subscribe(_ => OnAppInitialized());

Loading…
Cancel
Save