feat(archival): add IArchiveFiles with git implementation

This commit is contained in:
Collin M. Barrett 2020-09-09 19:22:04 -05:00
parent 38c8b991f1
commit 12d4b2f0ad
9 changed files with 119 additions and 7 deletions

4
.env
View file

@ -1,3 +1,7 @@
ARCHIVAL_GIT_REPOSITORY_DIRECTORY=archives
ARCHIVAL_GIT_USER_NAME=FilterLists Archival
ARCHIVAL_GIT_USER_EMAIL=noreply@filterlists.com
DIRECTORY_CONNECTION_STRING=Server=directory-db;Database=filterlists;User Id=filterlists;Password=filterlists;
DIRECTORY_DB_USER=filterlists
DIRECTORY_DB_PASSWORD=filterlists

View file

@ -1,16 +1,24 @@
using FilterLists.Archival.Application;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace FilterLists.Archival.Api
{
public class Startup
internal class Startup
{
public static void ConfigureServices(IServiceCollection services)
public Startup(IConfiguration configuration)
{
services.AddApplicationServices();
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddApplicationServices(Configuration);
}
public static void Configure(IApplicationBuilder app, IWebHostEnvironment env)

View file

@ -1,15 +1,16 @@
using FilterLists.Archival.Infrastructure;
using MediatR;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace FilterLists.Archival.Application
{
public static class ServiceCollectionExtension
{
public static void AddApplicationServices(this IServiceCollection services)
public static void AddApplicationServices(this IServiceCollection services, IConfiguration configuration)
{
services.AddMediatR(typeof(ServiceCollectionExtension).Assembly);
services.AddInfrastructureServices();
services.AddInfrastructureServices(configuration);
}
}
}

View file

@ -25,11 +25,14 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="LibGit2Sharp" Version="0.26.2" />
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="3.3.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.8" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.8" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.1.8" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,11 @@
namespace FilterLists.Archival.Infrastructure.Options
{
public class GitOptions
{
public const string Key = nameof(Key);
public string RepositoryDirectory { get; set; }
public string UserName { get; set; }
public string UserEmail { get; set; }
}
}

View file

@ -0,0 +1,42 @@
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using FilterLists.Archival.Infrastructure.Options;
using LibGit2Sharp;
using Microsoft.Extensions.Options;
namespace FilterLists.Archival.Infrastructure.Persistence
{
internal class GitFileArchiver : IArchiveFile
{
private readonly GitOptions _options;
private readonly IRepository _repository;
public GitFileArchiver(IOptions<GitOptions> gitOptions, IRepository gitRepository)
{
_options = gitOptions.Value;
_repository = gitRepository;
}
public async Task ArchiveFileAsync(
Stream fileContents,
string fileName,
CancellationToken cancellationToken = default)
{
await using var output = File.OpenWrite(fileName);
await fileContents.CopyToAsync(output, cancellationToken);
if (!cancellationToken.IsCancellationRequested)
Commit(fileName);
}
private void Commit(string fileName)
{
Commands.Stage(_repository, fileName);
var utcNow = DateTime.UtcNow;
var signature = new Signature(_options.UserName, _options.UserEmail, utcNow);
var message = $"archive {fileName}";
_repository.Commit(message, signature, signature);
}
}
}

View file

@ -0,0 +1,11 @@
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace FilterLists.Archival.Infrastructure.Persistence
{
public interface IArchiveFile
{
Task ArchiveFileAsync(Stream fileContents, string fileName, CancellationToken cancellationToken = default);
}
}

View file

@ -0,0 +1,25 @@
using FilterLists.Archival.Infrastructure.Options;
using LibGit2Sharp;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace FilterLists.Archival.Infrastructure.Persistence
{
public static class ServiceCollectionExtension
{
internal static void AddGitServices(this IServiceCollection services, IConfiguration configuration)
{
services.Configure<GitOptions>(configuration.GetSection(GitOptions.Key));
services.AddTransient<IRepository, Repository>(_ =>
{
var gitOptions = new GitOptions();
configuration.GetSection(GitOptions.Key).Bind(gitOptions);
if (!Repository.IsValid(gitOptions.RepositoryDirectory))
Repository.Init(gitOptions.RepositoryDirectory);
return new Repository(gitOptions.RepositoryDirectory);
});
}
}
}

View file

@ -1,11 +1,18 @@
using Microsoft.Extensions.DependencyInjection;
using System;
using FilterLists.Archival.Infrastructure.Persistence;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace FilterLists.Archival.Infrastructure
{
public static class ServiceCollectionExtension
{
public static void AddInfrastructureServices(this IServiceCollection services)
public static void AddInfrastructureServices(this IServiceCollection services, IConfiguration configuration)
{
_ = configuration ?? throw new ArgumentNullException(nameof(configuration));
services.AddGitServices(configuration);
services.AddTransient<IArchiveFile, GitFileArchiver>();
}
}
}