Skip to content

Commit

Permalink
New argument added for customizing end-of-line characters in output f…
Browse files Browse the repository at this point in the history
…iles (#6)

* Initial commit (#1)

* Initial commit
* Names refactoring
* Readme.md and license provided, fixed pipelines, usage examples, minor fixes, cleaning code

* Update README.md

* Transient vulnerabilities removed. Cleaning code.

* Tool version updated in examples

* Another enhancement to control end-of-line in created file

* fix: End-of-lines in YAML serialization

* Readme file updated

---------

Co-authored-by: Paweł Jankowski <[email protected]>
  • Loading branch information
antyrama and paweljankowski-columbus authored Mar 30, 2024
1 parent cb96ef3 commit 340b7af
Show file tree
Hide file tree
Showing 12 changed files with 99 additions and 16 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ Tool is customisable, take a look at list of all arguments that can be passed. E
| -y | --to-yaml | :heavy_check_mark: | Indicates whether configuration wrapped in YAML Azure DevOps variables file | `false` |
| -f | --file-path-template | :heavy_check_mark: | File name template for output. Template may contain a placeholder for environment name. Example: `configuration.{0}.json` | `./configuration.json` |
| -e | --environments | :heavy_check_mark: | A list of environment names. Separate configuration file will be created per each environment. Required when file name template contains placeholder | |
| -l | -eol | :heavy_check_mark: | Customize end-of-line characters, possible values: `Cr`, `CrLf` or `Lf`, when skipped, operating system default end-of-line characters will be used | |

### Configuration providers
If you'd like to include all the settings collected by different configuration provider, add them all by `--providers` option. More information about [configuration providers](https://learn.microsoft.com/en-us/dotnet/core/extensions/configuration-providers).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"antyrama.tools.scribe.cli": {
"version": "0.0.3-rc",
"version": "0.0.5",
"commands": [
"app-settings-to-file"
]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
Expand All @@ -7,7 +7,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Antyrama.Tools.Scribe.Core" Version="0.0.3-rc" />
<PackageReference Include="Antyrama.Tools.Scribe.Core" Version="0.0.5" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
</ItemGroup>

Expand Down
2 changes: 1 addition & 1 deletion examples/src/ExampleWebAppSimple/.config/dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"antyrama.tools.scribe.cli": {
"version": "0.0.3-rc",
"version": "0.0.5",
"commands": [
"app-settings-to-file"
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Antyrama.Tools.Scribe.Core" Version="0.0.3-rc" />
<PackageReference Include="Antyrama.Tools.Scribe.Core" Version="0.0.5" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ public void Generate()
.ToDictionary(s => s.Key, s => s.Value);

var repository = _options.WrapInYaml
? (ConfigurationRepository)new YamlConfigurationRepository(_options.YamlVariableName)
: new JsonConfigurationRepository();
? (ConfigurationRepository)new YamlConfigurationRepository(_options.YamlVariableName, _options)
: new JsonConfigurationRepository(_options);

foreach (var filename in GetConfigurationFiles(_options))
{
Expand All @@ -48,7 +48,7 @@ public void Generate()
}
}

private IReadOnlyDictionary<string, IReadOnlyDictionary<string, object>> Load(IConfigurationRepository repository, string filename)
private static IReadOnlyDictionary<string, IReadOnlyDictionary<string, object>> Load(IConfigurationRepository repository, string filename)
{
try
{
Expand All @@ -62,7 +62,7 @@ private IReadOnlyDictionary<string, IReadOnlyDictionary<string, object>> Load(IC
}
}

private void Save(IConfigurationRepository repository, string filename, IEnumerable<IReadOnlyDictionary<string, object>> settings)
private static void Save(IConfigurationRepository repository, string filename, IEnumerable<IReadOnlyDictionary<string, object>> settings)
{
using var stream = new FileStream(filename, FileMode.Create, FileAccess.Write);

Expand Down Expand Up @@ -119,6 +119,5 @@ private IEnumerable<string> GetConfigurationFiles(ToolInternalOptions options)
}

throw new InvalidOperationException("File path template must contain '{0}' as environment placeholder when environments specified.");

}
}
2 changes: 1 addition & 1 deletion src/Antyrama.Tools.Scribe.Core/ConfigurationCollector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public IReadOnlyList<KeyValuePair<string, string>> Collect(string pathSeparator)
return settings;
}

private void Collect(IConfigurationSection section, ICollection<KeyValuePair<string, string>> settings,
private static void Collect(IConfigurationSection section, ICollection<KeyValuePair<string, string>> settings,
string pathSeparator)
{
if (section == null || string.IsNullOrEmpty(section.Key))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,26 @@ internal interface IConfigurationRepository

internal abstract class ConfigurationRepository : IConfigurationRepository
{
protected readonly string Eol;

protected ConfigurationRepository(ToolInternalOptions options)
{
Eol = ResolveEndOfLine(options);
}

public abstract IReadOnlyDictionary<string, object>[] Load(Stream stream);

public abstract void Save(Stream stream, IEnumerable<IReadOnlyDictionary<string, object>> settings);

protected static string Serialize(IEnumerable<IReadOnlyDictionary<string, object>> settings)
protected string Serialize(IEnumerable<IReadOnlyDictionary<string, object>> settings)
{
var serialized = settings.Select(setting => $" {JsonConvert.SerializeObject(setting)}");

var separator = $",{Environment.NewLine}";
var separator = $",{Eol}";
var formatted = string.Join(separator, serialized)
.BeautifyJson();

return $"[{Environment.NewLine}{formatted}{Environment.NewLine}]";
return $"[{Eol}{formatted}{Eol}]";
}

protected static IReadOnlyDictionary<string, object>[] Deserialize(string settings)
Expand All @@ -43,4 +50,20 @@ protected static IReadOnlyDictionary<string, object>[] Deserialize(string settin
return Array.Empty<IReadOnlyDictionary<string, object>>();
}
}

private static string ResolveEndOfLine(ToolInternalOptions options)
{
return options.Eol switch
{
EndOfLine.Cr => Cr,
EndOfLine.CrLf => CrLf,
EndOfLine.Lf => Lf,
null => Environment.NewLine,
_ => throw new ArgumentOutOfRangeException(nameof(options))
};
}

private const string Cr = "\r";
private const string CrLf = "\r\n";
private const string Lf = "\n";
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ namespace Antyrama.Tools.Scribe.Core.Repository;

internal class JsonConfigurationRepository : ConfigurationRepository
{
public JsonConfigurationRepository(ToolInternalOptions options) : base(options)
{
}

public override IReadOnlyDictionary<string, object>[] Load(Stream stream)
{
try
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ internal class YamlConfigurationRepository : ConfigurationRepository
private readonly Serializer _serializer;
private readonly Deserializer _deserializer;

public YamlConfigurationRepository(string variableName)
public YamlConfigurationRepository(string variableName, ToolInternalOptions options)
: base(options)
{
_serializer = new SerializerBuilder()
.WithAttributeOverride<Variables>(variables => variables.AppConfig,
Expand Down Expand Up @@ -55,8 +56,11 @@ public override void Save(Stream stream, IEnumerable<IReadOnlyDictionary<string,
}
};

var yaml = _serializer.Serialize(root);
yaml = yaml.Replace(Environment.NewLine, Eol);

var writer = new StreamWriter(stream);
_serializer.Serialize(writer, root);
writer.Write(yaml);
writer.Flush();
}
}
15 changes: 15 additions & 0 deletions src/Antyrama.Tools.Scribe.Core/ToolOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ public class ToolOptions
[Option('e', "environments", Required = false, Default = new string[0],
HelpText = "A list of environment names. Separate configuration file will be created per each environment. Required when file name template contains placeholder.")]
public IEnumerable<string> EnvironmentsList { get; set; }

[Option('l', "eol", Required = false,
HelpText = "End-of-line delimiter, possible values: Cr, CrLf or Lf, by default operating system end-of-line will be used.")]
public EndOfLine? Eol { get; set; }
}

[Verb("_generate", Hidden = true)]
Expand Down Expand Up @@ -75,4 +79,15 @@ public class ToolInternalOptions
[Option('e', "environments", Required = false, Default = new string[0],
HelpText = "A list of environment names. Separate configuration file will be created per each environment. Required when file name template contains placeholder.")]
public IEnumerable<string> Environments { get; set; }

[Option('l', "eol", Required = false,
HelpText = "End-of-line delimiter, possible values: Cr, CrLf or Lf, by default operating system end-of-line will be used.")]
public EndOfLine? Eol { get; set; }
}

public enum EndOfLine
{
Cr,
CrLf,
Lf
}
37 changes: 37 additions & 0 deletions tests/UnitTests/Repository/JsonConfigurationRepositoryTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System.Text;
using Antyrama.Tools.Scribe.Core;
using Antyrama.Tools.Scribe.Core.Repository;
using FluentAssertions;

namespace UnitTests.Repository;

public sealed class JsonConfigurationRepositoryTests
{
[Theory]
[InlineData(EndOfLine.CrLf, "\r\n")]
[InlineData(EndOfLine.Cr, "\r")]
[InlineData(EndOfLine.Lf, "\n")]
public void ShouldWriteAndReadConfigFileWithAllPossibleEndOfLines(EndOfLine? eol, string eolChars)
{
// arrange
var options = new ToolInternalOptions { Eol = eol };
var sut = new JsonConfigurationRepository(options);

using var stream = new MemoryStream();

// act
sut.Save(stream,
new IReadOnlyDictionary<string, object>[]
{
new Dictionary<string, object> { { "key1", "value1" }, { "key2", "value2" } }
});

// assert
stream.Seek(0, SeekOrigin.Begin);

using var reader = new StreamReader(stream, Encoding.UTF8);
var result = reader.ReadToEnd();

result.Should().Contain(eolChars);
}
}

0 comments on commit 340b7af

Please sign in to comment.