diff --git a/Appy.GitDb.Core/Appy.GitDb.Core.csproj b/Appy.GitDb.Core/Appy.GitDb.Core.csproj
index 8fe82b2..29c7182 100644
--- a/Appy.GitDb.Core/Appy.GitDb.Core.csproj
+++ b/Appy.GitDb.Core/Appy.GitDb.Core.csproj
@@ -1,14 +1,14 @@
-
+
- net461;netstandard2.0
+ net10.0
1591
AnyCpu
- 0.14.0
+ 0.14.0
-
+
-
+
-
-
\ No newline at end of file
+
+
diff --git a/Appy.GitDb.Local/Appy.GitDb.Local.csproj b/Appy.GitDb.Local/Appy.GitDb.Local.csproj
index 60ca672..4d93885 100644
--- a/Appy.GitDb.Local/Appy.GitDb.Local.csproj
+++ b/Appy.GitDb.Local/Appy.GitDb.Local.csproj
@@ -1,18 +1,17 @@
-
+
- net461
+ net10.0
1591
AnyCpu
$(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage
0.17.0
-
+
-
-
-
-
+
+
+
@@ -24,8 +23,8 @@
-
+
-
\ No newline at end of file
+
diff --git a/Appy.GitDb.Local/LocalGitDb.cs b/Appy.GitDb.Local/LocalGitDb.cs
index 13ca8f3..ca3ee70 100644
--- a/Appy.GitDb.Local/LocalGitDb.cs
+++ b/Appy.GitDb.Local/LocalGitDb.cs
@@ -63,7 +63,7 @@ public LocalGitDb(string path, string remoteName = null, string remoteUrl = null
if (!string.IsNullOrEmpty(_remoteUrl))
{
_logger.Trace($"No repository exists on disk and there's a remote URL, cloning the repo from {_remoteUrl}");
- Repository.Clone(_remoteUrl, path, new CloneOptions {IsBare = true, CredentialsProvider = credentials});
+ Repository.Clone(_remoteUrl, path, new CloneOptions { IsBare = true, FetchOptions = { CredentialsProvider = credentials } });
}
else
{
diff --git a/Appy.GitDb.Remote/Appy.GitDb.Remote.csproj b/Appy.GitDb.Remote/Appy.GitDb.Remote.csproj
index 139edc9..eb5406e 100644
--- a/Appy.GitDb.Remote/Appy.GitDb.Remote.csproj
+++ b/Appy.GitDb.Remote/Appy.GitDb.Remote.csproj
@@ -1,22 +1,17 @@
-
-
+
+
- net461;netstandard2.0
+ net10.0
1591
- AnyCpu
+ AnyCpu
$(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage
0.18.0
-
+
-
+
-
-
-
-
-
true
@@ -26,8 +21,8 @@
-
+
-
\ No newline at end of file
+
diff --git a/Appy.GitDb.Remote/RemoteGitDb.cs b/Appy.GitDb.Remote/RemoteGitDb.cs
index c105d52..292a310 100644
--- a/Appy.GitDb.Remote/RemoteGitDb.cs
+++ b/Appy.GitDb.Remote/RemoteGitDb.cs
@@ -6,7 +6,7 @@
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
-using System.Web;
+using System.Net;
using Appy.GitDb.Core.Interfaces;
using Appy.GitDb.Core.Model;
using Newtonsoft.Json;
@@ -34,7 +34,7 @@ public RemoteGitDb(string userName, string password, string url, int batchSize =
string urlEncode(string value) =>
- HttpUtility.UrlEncode(value);
+ WebUtility.UrlEncode(value);
public Task Get(string branch, string key) =>
_client.GetAsync($"/{branch}/document/{urlEncode(key)}");
diff --git a/Appy.GitDb.Server/App.config b/Appy.GitDb.Server/App.config
deleted file mode 100644
index e3ed6b4..0000000
--- a/Appy.GitDb.Server/App.config
+++ /dev/null
@@ -1,65 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Appy.GitDb.Server/App.cs b/Appy.GitDb.Server/App.cs
index b1b86b7..6bc8eaf 100644
--- a/Appy.GitDb.Server/App.cs
+++ b/Appy.GitDb.Server/App.cs
@@ -1,76 +1,61 @@
-using System;
using System.Collections.Generic;
-using System.Web.Http;
-using System.Web.Http.ExceptionHandling;
using Appy.GitDb.Core.Interfaces;
using Appy.GitDb.Server.Auth;
using Appy.GitDb.Server.Logging;
-using Autofac;
-using Autofac.Integration.WebApi;
-using Microsoft.Owin.Extensions;
-using Microsoft.Owin.Hosting;
-using NLog;
-using Owin;
-using ExceptionLogger = Appy.GitDb.Server.Logging.ExceptionLogger;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using NLog.LayoutRenderers;
+using AppyExceptionLayoutRenderer = Appy.GitDb.Server.Logging.ExceptionLayoutRenderer;
namespace Appy.GitDb.Server
{
public class App
{
- App(){}
- IContainer _container;
- string _url;
- IEnumerable _users;
- Logger _serverLog;
+ App() { }
- public static App Create(string url, IGitDb repo, IEnumerable users)
+ static App()
{
- var builder = new ContainerBuilder();
- builder.RegisterInstance(repo).As().ExternallyOwned();
- builder.RegisterApiControllers(typeof(App).Assembly);
+ LayoutRenderer.Register("appy-exception");
+ LayoutRenderer.Register("correlationid");
+ }
- var app = new App
- {
- _container = builder.Build(),
- _url = url,
- _users = users,
- _serverLog = LogManager.GetLogger("server-log")
- };
- LoggingMiddleware.Logger = LogManager.GetLogger("server-log");
+ public static WebApplication Create(string url, IGitDb repo, IEnumerable users)
+ {
+ var builder = WebApplication.CreateBuilder();
+ builder.WebHost.UseUrls(url);
+ ConfigureServices(builder.Services, repo, users);
+ var app = builder.Build();
+ ConfigurePipeline(app);
return app;
}
- public IDisposable Start()
+ public static IWebHostBuilder CreateTestBuilder(IGitDb repo, IEnumerable users) =>
+ new WebHostBuilder()
+ .ConfigureServices(services => ConfigureServices(services, repo, users))
+ .Configure(ConfigurePipeline);
+
+ static void ConfigureServices(IServiceCollection services, IGitDb repo, IEnumerable users)
{
- try
- {
- _serverLog.Info("Starting up git server");
- var result = WebApp.Start(new StartOptions(_url), Configuration);
- _serverLog.Info($"Server started on {_url}");
- return result;
- }
- catch (Exception ex)
- {
- _serverLog.Fatal(ex, string.Empty);
- throw;
- }
+ services.AddSingleton(repo);
+ services.AddSingleton(users);
+ services.AddTransient();
+ services.AddAuthentication("Basic")
+ .AddScheme("Basic", null);
+ services.AddAuthorization();
+ services.AddResponseCompression();
+ services.AddControllers()
+ .AddNewtonsoftJson();
}
-
- public void Configuration(IAppBuilder app)
+ static void ConfigurePipeline(IApplicationBuilder app)
{
- var config = new HttpConfiguration();
- config.Services.Add(typeof(IExceptionLogger), new ExceptionLogger());
- app.UseAutofacMiddleware(_container);
- var auth = new Authentication(_users);
- app.UseBasicAuthentication("appy.gitdb", auth.ValidateUsernameAndPassword);
- config.MapHttpAttributeRoutes();
- config.DependencyResolver = new AutofacWebApiDependencyResolver(_container);
-
- app.Use();
- app.UseCompressionModule(OwinCompression.DefaultCompressionSettings);
- app.UseStageMarker(PipelineStage.MapHandler);
- app.UseWebApi(config);
+ app.UseMiddleware();
+ app.UseResponseCompression();
+ app.UseRouting();
+ app.UseAuthentication();
+ app.UseAuthorization();
+ app.UseEndpoints(endpoints => endpoints.MapControllers());
}
}
-}
\ No newline at end of file
+}
diff --git a/Appy.GitDb.Server/Appy.GitDb.Server.csproj b/Appy.GitDb.Server/Appy.GitDb.Server.csproj
index 6595878..2d7f496 100644
--- a/Appy.GitDb.Server/Appy.GitDb.Server.csproj
+++ b/Appy.GitDb.Server/Appy.GitDb.Server.csproj
@@ -1,153 +1,20 @@
-
-
-
+
+
- Debug
- AnyCPU
- {A9FAB943-9F28-49F8-82FB-0380A22FD683}
+ net10.0
Exe
- Properties
- Appy.GitDb.Server
- Appy.GitDb.Server
- v4.6.1
- 512
- true
+ enable
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
- ..\packages\Autofac.4.1.1\lib\net45\Autofac.dll
- True
-
-
- ..\packages\Autofac.Owin.4.0.0\lib\net45\Autofac.Integration.Owin.dll
- True
-
-
- ..\packages\Autofac.WebApi2.4.0.0\lib\net45\Autofac.Integration.WebApi.dll
- True
-
-
- ..\packages\Autofac.WebApi2.Owin.4.0.0\lib\net45\Autofac.Integration.WebApi.Owin.dll
- True
-
-
- ..\packages\FSharp.Core.4.1.17\lib\net45\FSharp.Core.dll
- True
-
-
- ..\packages\Microsoft.Owin.3.1.0\lib\net45\Microsoft.Owin.dll
-
-
- ..\packages\Microsoft.Owin.Host.HttpListener.3.0.1\lib\net45\Microsoft.Owin.Host.HttpListener.dll
- True
-
-
- ..\packages\Microsoft.Owin.Hosting.3.0.1\lib\net45\Microsoft.Owin.Hosting.dll
- True
-
-
- ..\packages\Microsoft.Owin.Security.2.1.0\lib\net45\Microsoft.Owin.Security.dll
- True
-
-
- ..\packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll
-
-
- ..\packages\NLog.4.4.9\lib\net45\NLog.dll
-
-
- ..\packages\Owin.1.0\lib\net40\Owin.dll
- True
-
-
- ..\packages\Owin.Compression.1.0.15\lib\net45\Owin.Compression.dll
-
-
-
-
-
- ..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll
- True
-
-
- ..\packages\System.ValueTuple.4.3.0\lib\netstandard1.0\System.ValueTuple.dll
-
-
- ..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll
- True
-
-
- ..\packages\Microsoft.AspNet.WebApi.Owin.5.2.3\lib\net45\System.Web.Http.Owin.dll
- True
-
-
-
- ..\packages\Thinktecture.IdentityModel.Owin.BasicAuthentication.1.0.1\lib\net45\Thinktecture.IdentityModel.Owin.BasicAuthentication.dll
- True
-
-
- ..\packages\YamlDotNet.5.4.0\lib\net45\YamlDotNet.dll
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
- Always
- Designer
-
-
- Designer
-
-
+
+
+
+
-
- {72ae8930-98ef-446d-8167-7dd251bcf4e6}
- Appy.GitDb.Core
-
-
- {37d87fb6-e7d6-4217-b021-38cea7233e6f}
- Appy.GitDb.Local
-
+
+
-
-
-
\ No newline at end of file
+
+
diff --git a/Appy.GitDb.Server/Auth/BasicAuthHandler.cs b/Appy.GitDb.Server/Auth/BasicAuthHandler.cs
new file mode 100644
index 0000000..cdeff83
--- /dev/null
+++ b/Appy.GitDb.Server/Auth/BasicAuthHandler.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Collections.Generic;
+using System.Security.Claims;
+using System.Text;
+using System.Text.Encodings.Web;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+
+namespace Appy.GitDb.Server.Auth
+{
+ public class BasicAuthOptions : AuthenticationSchemeOptions { }
+
+ public class BasicAuthHandler : AuthenticationHandler
+ {
+ readonly IEnumerable _users;
+
+ public BasicAuthHandler(
+ IOptionsMonitor options,
+ ILoggerFactory logger,
+ UrlEncoder encoder,
+ IEnumerable users)
+ : base(options, logger, encoder)
+ {
+ _users = users;
+ }
+
+ protected override Task HandleAuthenticateAsync()
+ {
+ if (!Request.Headers.TryGetValue("Authorization", out var authHeader))
+ return Task.FromResult(AuthenticateResult.NoResult());
+
+ try
+ {
+ var header = authHeader.ToString();
+ if (!header.StartsWith("Basic ", StringComparison.OrdinalIgnoreCase))
+ return Task.FromResult(AuthenticateResult.NoResult());
+
+ var credentials = Encoding.UTF8.GetString(Convert.FromBase64String(header["Basic ".Length..].Trim()));
+ var separatorIndex = credentials.IndexOf(':');
+ if (separatorIndex < 0)
+ return Task.FromResult(AuthenticateResult.Fail("Invalid credentials format"));
+
+ var userName = credentials[..separatorIndex];
+ var password = credentials[(separatorIndex + 1)..];
+
+ var authentication = new Authentication(_users);
+ var claims = authentication.ValidateUsernameAndPassword(userName, password).GetAwaiter().GetResult();
+
+ if (claims == null)
+ return Task.FromResult(AuthenticateResult.Fail("Invalid username or password"));
+
+ var identity = new ClaimsIdentity(claims, Scheme.Name);
+ var principal = new ClaimsPrincipal(identity);
+ var ticket = new AuthenticationTicket(principal, Scheme.Name);
+ return Task.FromResult(AuthenticateResult.Success(ticket));
+ }
+ catch (Exception ex)
+ {
+ return Task.FromResult(AuthenticateResult.Fail(ex));
+ }
+ }
+
+ protected override Task HandleChallengeAsync(AuthenticationProperties properties)
+ {
+ Response.Headers["WWW-Authenticate"] = "Basic realm=\"appy.gitdb\"";
+ Response.StatusCode = 401;
+ return Task.CompletedTask;
+ }
+ }
+}
diff --git a/Appy.GitDb.Server/GitApi.cs b/Appy.GitDb.Server/GitApi.cs
index 08abac0..adc8a51 100644
--- a/Appy.GitDb.Server/GitApi.cs
+++ b/Appy.GitDb.Server/GitApi.cs
@@ -1,15 +1,15 @@
-using System;
+using System;
using System.Collections.Generic;
-using System.Net;
-using System.Net.Http;
using System.Threading.Tasks;
-using System.Web.Http;
using Appy.GitDb.Core.Interfaces;
using Appy.GitDb.Core.Model;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
namespace Appy.GitDb.Server
{
- public class GitApiController : ApiController
+ [ApiController]
+ public class GitApiController : ControllerBase
{
readonly IGitDb _gitDb;
@@ -21,55 +21,55 @@ public GitApiController(IGitDb gitDb)
[Route("{branch}/document/{*key}")]
[HttpGet]
[Authorize(Roles = "admin, read")]
- public Task Get(string branch, string key) =>
+ public Task Get(string branch, string key) =>
result(() => _gitDb.Get(branch, key));
[Route("{branch}/documents/{*key}")]
[HttpGet]
[Authorize(Roles = "admin, read")]
- public Task GetFiles(string branch, string key) =>
+ public Task GetFiles(string branch, string key) =>
result(() => _gitDb.GetFiles(branch, key));
[Route("{branch}/{start}/{pageSize}/documents/{*key}")]
[HttpGet]
[Authorize(Roles = "admin, read")]
- public Task GetFilesPaged(string branch, string key, int start, int pageSize) =>
+ public Task GetFilesPaged(string branch, string key, int start, int pageSize) =>
result(() => _gitDb.GetFilesPaged(branch, key, start, pageSize));
[Route("{branch}/document")]
[HttpPost]
[Authorize(Roles = "admin,write")]
- public Task Save(string branch, [FromBody] SaveRequest request) =>
+ public Task Save(string branch, [FromBody] SaveRequest request) =>
result(() => _gitDb.Save(branch, request.Message, request.Document, request.Author));
[Route("{branch}/document/delete")]
[HttpPost]
[Authorize(Roles = "admin,write")]
- public Task Delete(string branch, [FromBody] DeleteRequest request) =>
+ public Task Delete(string branch, [FromBody] DeleteRequest request) =>
result(() => _gitDb.Delete(branch, request.Key, request.Message, request.Author));
[Route("{branch}/transactions/close")]
[HttpPost]
[Authorize(Roles = "admin,write")]
- public Task CloseTransactions(string branch) =>
+ public Task CloseTransactions(string branch) =>
result(() => _gitDb.CloseTransactions(branch));
[Route("tag")]
[HttpPost]
[Authorize(Roles = "admin,write")]
- public Task Tag([FromBody] Reference reference) =>
+ public Task Tag([FromBody] Reference reference) =>
result(() => _gitDb.Tag(reference));
[Route("branch")]
[HttpGet]
[Authorize(Roles = "admin,read")]
- public Task GetBranches() =>
+ public Task GetBranches() =>
result(() => _gitDb.GetAllBranches());
[Route("branch")]
[HttpPost]
[Authorize(Roles = "admin,write")]
- public Task CreateBranch([FromBody] Reference reference) =>
+ public Task CreateBranch([FromBody] Reference reference) =>
result(() => _gitDb.CreateBranch(reference));
static readonly Dictionary _transactions = new Dictionary();
@@ -77,7 +77,7 @@ public Task CreateBranch([FromBody] Reference reference) =>
[Route("{branch}/transaction")]
[HttpPost]
[Authorize(Roles = "admin,write")]
- public Task CreateTransaction(string branch) =>
+ public Task CreateTransaction(string branch) =>
result(async () =>
{
var trans = await _gitDb.CreateTransaction(branch);
@@ -89,45 +89,43 @@ public Task CreateTransaction(string branch) =>
[Route("{branch}")]
[HttpDelete]
[Authorize(Roles = "admin,write")]
- public Task DeleteBranch(string branch) =>
+ public Task DeleteBranch(string branch) =>
result(() => _gitDb.DeleteBranch(branch));
[Route("tag/{tag}")]
[HttpDelete]
[Authorize(Roles = "admin,write")]
- public Task DeleteTag(string tag) =>
+ public Task DeleteTag(string tag) =>
result(() => _gitDb.DeleteTag(tag));
[Route("{transactionId}/add")]
[HttpPost]
[Authorize(Roles = "admin,write")]
- public Task AddToTransaction(string transactionId, Document document) =>
+ public Task AddToTransaction(string transactionId, Document document) =>
result(() => _transactions[transactionId].Add(document));
[Route("{transactionId}/addmany")]
[HttpPost]
[Authorize(Roles = "admin,write")]
- public Task AddToTransaction(string transactionId, List documents) =>
+ public Task AddManyToTransaction(string transactionId, List documents) =>
result(() => _transactions[transactionId].AddMany(documents));
-
[Route("{transactionId}/delete/{key}")]
[HttpPost]
[Authorize(Roles = "admin,write")]
- public Task DeleteInTransaction(string transactionId, string key) =>
+ public Task DeleteInTransaction(string transactionId, string key) =>
result(() => _transactions[transactionId].Delete(key));
[Route("{transactionId}/deleteMany")]
[HttpPost]
[Authorize(Roles = "admin,write")]
- public Task DeleteInTransaction(string transactionId, List keys) =>
+ public Task DeleteManyInTransaction(string transactionId, List keys) =>
result(() => _transactions[transactionId].DeleteMany(keys));
-
[Route("{transactionId}/commit")]
[HttpPost]
[Authorize(Roles = "admin,write")]
- public Task CommitTransaction(string transactionId, [FromBody] CommitTransaction commit) =>
+ public Task CommitTransaction(string transactionId, [FromBody] CommitTransaction commit) =>
result(async () =>
{
var transaction = _transactions[transactionId];
@@ -139,7 +137,7 @@ public Task CommitTransaction(string transactionId, [FromBody
[Route("{transactionId}/abort")]
[HttpPost]
[Authorize(Roles = "admin,write")]
- public Task AbortTransaction(string transactionId) =>
+ public Task AbortTransaction(string transactionId) =>
result(async () =>
{
var transaction = _transactions[transactionId];
@@ -150,29 +148,28 @@ public Task AbortTransaction(string transactionId) =>
[Route("merge")]
[HttpPost]
[Authorize(Roles = "admin,write")]
- public Task Merge(MergeRequest mergeRequest) =>
- result(() =>_gitDb.MergeBranch(mergeRequest.Source, mergeRequest.Target, mergeRequest.Author, mergeRequest.Message));
+ public Task Merge(MergeRequest mergeRequest) =>
+ result(() => _gitDb.MergeBranch(mergeRequest.Source, mergeRequest.Target, mergeRequest.Author, mergeRequest.Message));
[Route("{branch}/rebase")]
[HttpPost]
[Authorize(Roles = "admin,write")]
- public Task Rebase(RebaseRequest rebaseRequest) =>
+ public Task Rebase(RebaseRequest rebaseRequest) =>
result(() => _gitDb.RebaseBranch(rebaseRequest.Source, rebaseRequest.Target, rebaseRequest.Author, rebaseRequest.Message));
[Route("diff/{reference}/{reference2}")]
[HttpGet]
[Authorize(Roles = "admin,read")]
- public Task Diff(string reference, string reference2) =>
+ public Task Diff(string reference, string reference2) =>
result(() => _gitDb.Diff(reference, reference2));
[Route("log/{reference}/{reference2}")]
[HttpGet]
[Authorize(Roles = "admin,read")]
- public Task Log(string reference, string reference2) =>
+ public Task Log(string reference, string reference2) =>
result(() => _gitDb.Log(reference, reference2));
-
- async Task result(Func> action)
+ async Task result(Func> action)
{
try
{
@@ -180,15 +177,15 @@ async Task result(Func> action)
}
catch (ArgumentException ex)
{
- throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.BadRequest) {Content = new StringContent(ex.Message)});
+ return BadRequest(ex.Message);
}
catch (NotSupportedException ex)
{
- throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.BadRequest) { Content = new StringContent(ex.Message) });
+ return BadRequest(ex.Message);
}
}
- async Task result(Func action)
+ async Task result(Func action)
{
try
{
@@ -197,13 +194,12 @@ async Task result(Func action)
}
catch (ArgumentException ex)
{
- throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.BadRequest) {Content = new StringContent(ex.Message)});
+ return BadRequest(ex.Message);
}
catch (NotSupportedException ex)
{
- throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.BadRequest) { Content = new StringContent(ex.Message) });
+ return BadRequest(ex.Message);
}
}
-
}
-}
\ No newline at end of file
+}
diff --git a/Appy.GitDb.Server/GitProtocol.cs b/Appy.GitDb.Server/GitProtocol.cs
index 900a463..9864771 100644
--- a/Appy.GitDb.Server/GitProtocol.cs
+++ b/Appy.GitDb.Server/GitProtocol.cs
@@ -1,65 +1,76 @@
-using System;
-using System.Configuration;
+using System;
using System.Diagnostics;
using System.IO;
-using System.Net;
-using System.Net.Http;
-using System.Net.Http.Headers;
-using System.Threading;
+using System.Text;
using System.Threading.Tasks;
-using System.Web.Http;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Configuration;
namespace Appy.GitDb.Server
{
- [RoutePrefix("server")]
- public class GitProtocolController : ApiController
+ [ApiController]
+ [Route("server")]
+ public class GitProtocolController : ControllerBase
{
const string FlushMessage = "0000";
- readonly string _gitPath = ConfigurationManager.AppSettings["git.path"];
- readonly string _gitHomePath = ConfigurationManager.AppSettings["git.homePath"];
- readonly string _repoPath = ConfigurationManager.AppSettings["git.repository.path"];
+ readonly string _gitPath;
+ readonly string _gitHomePath;
+ readonly string _repoPath;
- [HttpGet]
- [Route("repository.git")]
+ public GitProtocolController(IConfiguration config)
+ {
+ _gitPath = config["git.path"];
+ _gitHomePath = config["git.homePath"];
+ _repoPath = config["git.repository.path"];
+ }
+
+ [HttpGet("repository.git")]
[Authorize(Roles = "admin, read")]
- public IHttpActionResult GitUrl() =>
- Ok();
+ public IActionResult GitUrl() => Ok();
- [HttpGet]
- [Route("repository.git/info/refs")]
+ [HttpGet("repository.git/info/refs")]
[Authorize(Roles = "admin, read")]
- public IHttpActionResult InfoRefs(string service) =>
- new GitResult(
- Request,
- $"application/x-{service}-advertisement",
- (input, outStream) => executeServiceByName(input, outStream, service.Substring(4), true, false),
- formatMessage($"# service={service}\n") + FlushMessage);
-
- [HttpPost, Route("repository.git/git-upload-pack")]
+ public IActionResult InfoRefs([FromQuery] string service)
+ {
+ var contentType = $"application/x-{service}-advertisement";
+ var preamble = formatMessage($"# service={service}\n") + FlushMessage;
+ return new GitStreamResult(
+ contentType,
+ async (input, output) =>
+ {
+ var writer = new StreamWriter(output, leaveOpen: true);
+ writer.Write(preamble);
+ await writer.FlushAsync();
+ await executeServiceByName(input, output, service.Substring(4), true, false);
+ });
+ }
+
+ [HttpPost("repository.git/git-upload-pack")]
[Authorize(Roles = "admin, read")]
- public IHttpActionResult UploadPack() =>
- new GitResult(Request,
- "application/x-git-upload-pack-result",
- (input, outStream) => executeServiceByName(input, outStream, "upload-pack", false, true));
+ public IActionResult UploadPack() =>
+ new GitStreamResult(
+ "application/x-git-upload-pack-result",
+ (input, output) => executeServiceByName(input, output, "upload-pack", false, true));
- [HttpPost, Route("repository.git/git-receive-pack")]
+ [HttpPost("repository.git/git-receive-pack")]
[Authorize(Roles = "admin, write")]
- public IHttpActionResult ReceivePack() =>
- new GitResult(Request,
- "application/x-git-receive-pack-result",
- (input, outStream) => executeServiceByName(input, outStream, "receive-pack", false, false));
+ public IActionResult ReceivePack() =>
+ new GitStreamResult(
+ "application/x-git-receive-pack-result",
+ (input, output) => executeServiceByName(input, output, "receive-pack", false, false));
- static string formatMessage(string input) =>
+ static string formatMessage(string input) =>
(input.Length + 4).ToString("X").PadLeft(4, '0') + input;
async Task executeServiceByName(Stream input, Stream output, string serviceName, bool addAdvertiseRefs, bool closeInput)
{
- var args = serviceName + " --stateless-rpc";
+ var args = new StringBuilder(serviceName).Append(" --stateless-rpc");
if (addAdvertiseRefs)
- args += " --advertise-refs";
- args += " \"" + _repoPath + "\"";
+ args.Append(" --advertise-refs");
+ args.Append($" \"{_repoPath}\"");
- var info = new ProcessStartInfo(_gitPath + @"\git.exe", args)
+ var info = new ProcessStartInfo(Path.Combine(_gitPath, "git.exe"), args.ToString())
{
CreateNoWindow = true,
RedirectStandardError = true,
@@ -73,57 +84,39 @@ async Task executeServiceByName(Stream input, Stream output, string serviceName,
info.EnvironmentVariables.Remove("HOME");
info.EnvironmentVariables.Add("HOME", _gitHomePath);
- using (var process = Process.Start(info))
- {
- await input.CopyToAsync(process.StandardInput.BaseStream);
- if (closeInput)
- process.StandardInput.Close();
- else
- process.StandardInput.Write('\0');
-
- await process.StandardOutput.BaseStream.CopyToAsync(output);
- process.WaitForExit();
- }
- }
+ using var process = Process.Start(info);
+ await input.CopyToAsync(process.StandardInput.BaseStream);
+ if (closeInput)
+ process.StandardInput.Close();
+ else
+ process.StandardInput.Write('\0');
+
+ await process.StandardOutput.BaseStream.CopyToAsync(output);
+ process.WaitForExit();
+ }
}
- public class GitResult : IHttpActionResult
+ public class GitStreamResult : IActionResult
{
- readonly HttpRequestMessage _request;
readonly string _contentType;
- readonly string _advertiseRefsContent;
- readonly Func _executeGitCommand;
+ readonly Func _execute;
- public GitResult(HttpRequestMessage request, string contentType, Func executeGitCommand, string advertiseRefsContent = null)
+ public GitStreamResult(string contentType, Func execute)
{
- _request = request;
_contentType = contentType;
- _advertiseRefsContent = advertiseRefsContent;
- _executeGitCommand = executeGitCommand;
+ _execute = execute;
}
- public async Task ExecuteAsync(CancellationToken cancellationToken)
+ public async Task ExecuteResultAsync(ActionContext context)
{
- var resp = _request.CreateResponse(HttpStatusCode.OK);
- var input = await _request.Content.ReadAsStreamAsync();
- resp.Content = new PushStreamContent(async (output, content, context) =>
- {
- if (_advertiseRefsContent != null)
- {
- var writer = new StreamWriter(output);
- writer.Write(_advertiseRefsContent);
- await writer.FlushAsync();
- }
- await _executeGitCommand(input, output);
- output.Close();
- });
-
- resp.Content.Headers.Expires = DateTimeOffset.MinValue;
- resp.Headers.Add("pragma", "no-cache");
- resp.Headers.CacheControl = CacheControlHeaderValue.Parse("no-cache, max-age=0, must-revalidate");
- resp.Content.Headers.ContentType = new MediaTypeHeaderValue(_contentType);
-
- return resp;
+ var response = context.HttpContext.Response;
+ response.ContentType = _contentType;
+ response.Headers["Pragma"] = "no-cache";
+ response.Headers["Cache-Control"] = "no-cache, max-age=0, must-revalidate";
+ response.Headers["Expires"] = DateTimeOffset.MinValue.ToString("R");
+
+ var input = context.HttpContext.Request.Body;
+ await _execute(input, response.Body);
}
}
-}
\ No newline at end of file
+}
diff --git a/Appy.GitDb.Server/Logging/ExceptionLogger.cs b/Appy.GitDb.Server/Logging/ExceptionLogger.cs
deleted file mode 100644
index 192c4c3..0000000
--- a/Appy.GitDb.Server/Logging/ExceptionLogger.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System.Net.Http;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Web.Http.ExceptionHandling;
-
-namespace Appy.GitDb.Server.Logging
-{
- public class ExceptionLogger : IExceptionLogger
- {
- public Task LogAsync(ExceptionLoggerContext context, CancellationToken cancellationToken)
- {
- context.Request.GetOwinContext().Set("exception", context.Exception);
- return Task.CompletedTask;
- }
- }
-}
diff --git a/Appy.GitDb.Server/Logging/LogContext.cs b/Appy.GitDb.Server/Logging/LogContext.cs
index 4e3cb55..ae30054 100644
--- a/Appy.GitDb.Server/Logging/LogContext.cs
+++ b/Appy.GitDb.Server/Logging/LogContext.cs
@@ -1,5 +1,5 @@
-using System;
-using System.Runtime.Remoting.Messaging;
+using System;
+using System.Threading;
using NLog;
namespace Appy.GitDb.Server.Logging
@@ -7,6 +7,7 @@ namespace Appy.GitDb.Server.Logging
public class LogContext : IDisposable
{
const string CorrelationIdKey = "lctx:correlationid";
+ static readonly AsyncLocal _correlationId = new();
public string CorrelationId { get; }
@@ -21,19 +22,17 @@ public void Dispose() =>
public static void SetCorrelationId(string correlationId)
{
- CallContext.LogicalSetData(CorrelationIdKey, correlationId);
+ _correlationId.Value = correlationId;
MappedDiagnosticsLogicalContext.Set(CorrelationIdKey, correlationId);
}
public static void Clear()
{
- CallContext.LogicalSetData(CorrelationIdKey, null);
+ _correlationId.Value = null;
MappedDiagnosticsLogicalContext.Clear();
}
- public static string GetCorrelationId() => get(CorrelationIdKey);
-
- static string get(string key) =>
- CallContext.LogicalGetData(key) as string ?? MappedDiagnosticsLogicalContext.Get(key);
+ public static string GetCorrelationId() =>
+ _correlationId.Value ?? MappedDiagnosticsLogicalContext.Get(CorrelationIdKey);
}
}
diff --git a/Appy.GitDb.Server/Logging/LoggingMiddleWare.cs b/Appy.GitDb.Server/Logging/LoggingMiddleWare.cs
index cf341e1..1d00255 100644
--- a/Appy.GitDb.Server/Logging/LoggingMiddleWare.cs
+++ b/Appy.GitDb.Server/Logging/LoggingMiddleWare.cs
@@ -1,84 +1,65 @@
-using System;
+using System;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
-using Microsoft.Owin;
+using Microsoft.AspNetCore.Http;
using NLog;
namespace Appy.GitDb.Server.Logging
{
- public class LoggingMiddleware : OwinMiddleware
+ public class LoggingMiddleware : IMiddleware
{
- public static Logger Logger;
- public LoggingMiddleware(OwinMiddleware next) : base(next){ }
- public override async Task Invoke(IOwinContext context)
- {
- var correlationid = context.Request.Headers["X-FORWARD-CORRELATIONID"] ?? Guid.NewGuid().ToString("N");
-
- LogContext.SetCorrelationId(correlationid);
-
- context.Response.OnSendingHeaders(state =>
- {
- var ctx = state as IOwinContext;
- if (ctx == null) return;
- if (!ctx.Response.Headers.ContainsKey("correlationid"))
- ctx.Response.Headers.Add("correlationid", new[] { correlationid });
- }, context);
-
- var watch = new Stopwatch();
- watch.Start();
+ public static Logger Logger = LogManager.GetLogger("server-log");
- await Next.Invoke(context);
+ public async Task InvokeAsync(HttpContext context, RequestDelegate next)
+ {
+ var correlationId = context.Request.Headers["X-FORWARD-CORRELATIONID"].FirstOrDefault()
+ ?? Guid.NewGuid().ToString("N");
- watch.Stop();
+ LogContext.SetCorrelationId(correlationId);
+ context.Response.Headers["correlationid"] = correlationId;
- var identity = context.Request.User?.Identity;
- var userName = identity?.Name;
- var user = !string.IsNullOrEmpty(userName)
- ? userName
- : "(anonymous)";
+ var watch = Stopwatch.StartNew();
+ Exception caughtException = null;
- var exception = context.Environment.ContainsKey("exception")
- ? (Exception)context.Environment["exception"]
- : null;
+ try
+ {
+ await next(context);
+ }
+ catch (Exception ex)
+ {
+ caughtException = ex;
+ throw;
+ }
+ finally
+ {
+ watch.Stop();
+ var userName = context.User?.Identity?.Name ?? "(anonymous)";
- LogLevel level;
- if (exception != null || context.Response.StatusCode >= 500)
- level = LogLevel.Error;
- else if (context.Response.StatusCode >= 400)
- level = LogLevel.Warn;
- else
- level = LogLevel.Trace;
-
+ var level = caughtException != null || context.Response.StatusCode >= 500
+ ? LogLevel.Error
+ : context.Response.StatusCode >= 400
+ ? LogLevel.Warn
+ : LogLevel.Trace;
- Logger.Log(new LogEventInfo
- {
- Level = level,
- Exception = exception,
- LoggerName = "http-log",
- Properties =
+ Logger.Log(new LogEventInfo
{
- { "user", user},
- { "method", context.Request.Method},
- { "url", context.Request.Uri.AbsolutePath},
- { "querystring", context.Request.Uri.Query},
- { "request-headers", toLogString(context.Request.Headers)},
- { "response-headers", toLogString(context.Response.Headers) },
- { "statuscode", context.Response.StatusCode },
- { "reason", context.Response.ReasonPhrase },
- { "duration", watch.Elapsed.TotalMilliseconds },
- { "useragent", getValue(context.Request.Headers, "User-Agent") },
- { "host", context.Request.Uri.Host }
- }
- });
+ Level = level,
+ Exception = caughtException,
+ LoggerName = "http-log",
+ Properties =
+ {
+ { "user", userName },
+ { "method", context.Request.Method },
+ { "url", context.Request.Path.Value },
+ { "querystring", context.Request.QueryString.Value },
+ { "statuscode", context.Response.StatusCode },
+ { "duration", watch.Elapsed.TotalMilliseconds },
+ { "useragent", context.Request.Headers["User-Agent"].FirstOrDefault() ?? string.Empty },
+ { "host", context.Request.Host.Value }
+ }
+ });
+ }
}
-
- static string toLogString(IHeaderDictionary headers) =>
- string.Join("\n", headers.Select(kv => kv.Key + ": " + string.Join(" ", kv.Value)));
-
- static string getValue(IHeaderDictionary headers, string key) =>
- headers.ContainsKey(key)
- ? string.Join(" ", headers[key])
- : string.Empty;
}
-}
\ No newline at end of file
+}
diff --git a/Appy.GitDb.Server/NLog.config b/Appy.GitDb.Server/NLog.config
index f32cb58..05d3694 100644
--- a/Appy.GitDb.Server/NLog.config
+++ b/Appy.GitDb.Server/NLog.config
@@ -1,5 +1,5 @@
-
+
+ encoding="utf-8">
diff --git a/Appy.GitDb.Server/Program.cs b/Appy.GitDb.Server/Program.cs
index 5611086..8c7354b 100644
--- a/Appy.GitDb.Server/Program.cs
+++ b/Appy.GitDb.Server/Program.cs
@@ -1,11 +1,8 @@
-using System;
using System.Collections.Generic;
-using System.Configuration;
using Appy.GitDb.Local;
using Appy.GitDb.Server.Auth;
using Appy.GitDb.Server.Logging;
-using NLog.LayoutRenderers;
-using ExceptionLayoutRenderer = Appy.GitDb.Server.Logging.ExceptionLayoutRenderer;
+using Microsoft.Extensions.Configuration;
namespace Appy.GitDb.Server
{
@@ -13,30 +10,31 @@ class Program
{
public static void Main(string[] args)
{
- LayoutRenderer.Register("appy-exception");
- LayoutRenderer.Register("correlationid");
- var url = ConfigurationManager.AppSettings["server.url"];
- var gitRepoPath = ConfigurationManager.AppSettings["git.repository.path"];
- var remoteName = ConfigurationManager.AppSettings["remote.name"];
- var remoteUrl = ConfigurationManager.AppSettings["remote.url"];
- var userName = ConfigurationManager.AppSettings["remote.user.name"];
- var userEmail = ConfigurationManager.AppSettings["remote.user.email"];
- var password = ConfigurationManager.AppSettings["remote.user.password"];
- var remoteBranchSync = ConfigurationManager.AppSettings["remote.branch.sync"];
- if (!int.TryParse(ConfigurationManager.AppSettings["transactions.timeout"], out int transactionTimeout))
+ var config = new ConfigurationBuilder()
+ .AddJsonFile("appsettings.json", optional: true)
+ .AddEnvironmentVariables()
+ .AddCommandLine(args)
+ .Build();
+
+ var url = config["server.url"] ?? "http://+:9500";
+ var gitRepoPath = config["git.repository.path"];
+ var remoteName = config["remote.name"];
+ var remoteUrl = config["remote.url"];
+ var userName = config["remote.user.name"];
+ var userEmail = config["remote.user.email"];
+ var password = config["remote.user.password"];
+ var remoteBranchSync = config["remote.branch.sync"];
+ if (!int.TryParse(config["transactions.timeout"], out int transactionTimeout))
transactionTimeout = 10;
var app = App.Create(url, new LocalGitDb(gitRepoPath, remoteName, remoteUrl, userName, userEmail, password, remoteBranchSync, transactionTimeout), new List
{
- new User{ UserName = "GitAdmin", Password = ConfigurationManager.AppSettings["GitAdmin"], Roles = new [] { "admin","read","write" }},
- new User{ UserName = "GitReader",Password = ConfigurationManager.AppSettings["GitAdmin"],Roles = new [] { "read" }},
- new User{ UserName = "GitWriter", Password = ConfigurationManager.AppSettings["GitWriter"] ,Roles = new [] { "write" }}
+ new User { UserName = "GitAdmin", Password = config["GitAdmin"], Roles = new[] { "admin", "read", "write" } },
+ new User { UserName = "GitReader", Password = config["GitAdmin"], Roles = new[] { "read" } },
+ new User { UserName = "GitWriter", Password = config["GitWriter"], Roles = new[] { "write" } }
});
- using (app.Start())
- {
- Console.WriteLine("Press any key to exit");
- Console.ReadKey();
- }
+
+ app.Run();
}
}
}
diff --git a/Appy.GitDb.Server/Properties/AssemblyInfo.cs b/Appy.GitDb.Server/Properties/AssemblyInfo.cs
deleted file mode 100644
index b9c061e..0000000
--- a/Appy.GitDb.Server/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System.Reflection;
-using System.Runtime.InteropServices;
-
-[assembly: AssemblyTitle("Appy.GitDb.Server")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("AppyParking")]
-[assembly: AssemblyProduct("Appy.GitDb.Server")]
-[assembly: AssemblyCopyright("Copyright © 2016")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-[assembly: ComVisible(false)]
-
-[assembly: Guid("a9fab943-9f28-49f8-82fb-0380a22fd683")]
-
-[assembly: AssemblyVersion("1.0.*")]
\ No newline at end of file
diff --git a/Appy.GitDb.Server/appsettings.json b/Appy.GitDb.Server/appsettings.json
new file mode 100644
index 0000000..d6768d8
--- /dev/null
+++ b/Appy.GitDb.Server/appsettings.json
@@ -0,0 +1,16 @@
+{
+ "server.url": "http://+:9500",
+ "git.repository.path": "",
+ "remote.name": "",
+ "remote.url": "",
+ "remote.user.name": "",
+ "remote.user.email": "",
+ "remote.user.password": "",
+ "remote.branch.sync": "",
+ "transactions.timeout": "10",
+ "GitAdmin": "",
+ "GitReader": "",
+ "GitWriter": "",
+ "git.path": "",
+ "git.homePath": ""
+}
diff --git a/Appy.GitDb.Server/packages.config b/Appy.GitDb.Server/packages.config
deleted file mode 100644
index 2e6cf6a..0000000
--- a/Appy.GitDb.Server/packages.config
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Appy.GitDb.Tests/Appy.GitDb.Tests.csproj b/Appy.GitDb.Tests/Appy.GitDb.Tests.csproj
index b5c795f..b0ab7d7 100644
--- a/Appy.GitDb.Tests/Appy.GitDb.Tests.csproj
+++ b/Appy.GitDb.Tests/Appy.GitDb.Tests.csproj
@@ -1,186 +1,34 @@
-
-
-
-
-
+
+
- Debug
- AnyCPU
- {1C2D86C4-8CAD-457E-B4F1-86A5523B3112}
- Library
- Properties
- Appy.GitDb.Tests
- Appy.GitDb.Tests
- v4.6.1
- 512
-
-
+ net10.0
+ false
+ enable
+ true
-
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
- ..\packages\Castle.Core.3.3.3\lib\net45\Castle.Core.dll
- True
-
-
- ..\packages\FluentAssertions.4.14.0\lib\net45\FluentAssertions.dll
- True
-
-
- ..\packages\FluentAssertions.4.14.0\lib\net45\FluentAssertions.Core.dll
- True
-
-
- ..\packages\FSharp.Core.4.1.17\lib\net45\FSharp.Core.dll
- True
-
-
- ..\packages\LibGit2Sharp.0.26.2\lib\net46\LibGit2Sharp.dll
-
-
- ..\packages\Microsoft.Owin.3.1.0\lib\net45\Microsoft.Owin.dll
-
-
- ..\packages\Microsoft.Owin.Host.HttpListener.3.0.1\lib\net45\Microsoft.Owin.Host.HttpListener.dll
- True
-
-
- ..\packages\Microsoft.Owin.Hosting.3.0.1\lib\net45\Microsoft.Owin.Hosting.dll
- True
-
-
- ..\packages\Microsoft.Owin.Testing.3.0.1\lib\net45\Microsoft.Owin.Testing.dll
- True
-
-
- ..\packages\Moq.4.5.22\lib\net45\Moq.dll
- True
-
-
- ..\packages\Moq.AutoMock.0.4.0.0\lib\net40\Moq.AutoMock.dll
- True
-
-
- ..\packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll
-
-
- ..\packages\NLog.4.4.9\lib\net45\NLog.dll
-
-
- ..\packages\Owin.1.0\lib\net40\Owin.dll
- True
-
-
-
-
- ..\packages\System.ValueTuple.4.3.0\lib\netstandard1.0\System.ValueTuple.dll
-
-
-
-
-
- ..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll
- True
-
-
- ..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll
- True
-
-
- ..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll
- True
-
-
- ..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll
- True
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Always
-
-
-
+
-
- {72ae8930-98ef-446d-8167-7dd251bcf4e6}
- Appy.GitDb.Core
-
-
- {37d87fb6-e7d6-4217-b021-38cea7233e6f}
- Appy.GitDb.Local
-
-
- {3F7A7050-68CB-4D7F-9149-A59095EB78A1}
- Appy.GitDb.Remote
-
-
- {A9FAB943-9F28-49F8-82FB-0380A22FD683}
- Appy.GitDb.Server
-
-
- {e3eba271-650e-4482-bdea-41f569051b4d}
- Appy.GitDb.Watcher
-
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers
+
+
+
+
+
-
+
+
+
+
+
-
-
-
-
- This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
-
-
-
-
-
\ No newline at end of file
+
+
diff --git a/Appy.GitDb.Tests/Merging.cs b/Appy.GitDb.Tests/Merging.cs
index aa9ec70..68683c7 100644
--- a/Appy.GitDb.Tests/Merging.cs
+++ b/Appy.GitDb.Tests/Merging.cs
@@ -77,11 +77,11 @@ async Task removeItems(string branch, int start, int count)
[Fact]
public void FirstMergesShouldSuccedWithValidInfo() =>
- _firstMergeResult.ShouldBeEquivalentTo(MergeInfo.Succeeded("test2", "master", _commitBeforeSecondMerge));
+ _firstMergeResult.Should().BeEquivalentTo(MergeInfo.Succeeded("test2", "master", _commitBeforeSecondMerge));
[Fact]
public void SecondMergeShouldSuccedWithValidInfo() =>
- _secondMergeResult.ShouldBeEquivalentTo(MergeInfo.Succeeded("test", "master", _commitAfterSecondMerge));
+ _secondMergeResult.Should().BeEquivalentTo(MergeInfo.Succeeded("test", "master", _commitAfterSecondMerge));
[Fact]
public async Task AddsTheCorrectFilesToMaster() =>
@@ -126,7 +126,7 @@ protected override async Task Because()
[Fact]
public void MergeShouldSuccedWithValidInfo() =>
- _mergeResult.ShouldBeEquivalentTo(MergeInfo.Succeeded("test", "master", string.Empty));
+ _mergeResult.Should().BeEquivalentTo(MergeInfo.Succeeded("test", "master", string.Empty));
[Fact]
public void DoesNotCreateACommitOnMaster() =>
@@ -179,7 +179,7 @@ public void ShouldNotSucceedAndReturnConflicts()
c.TargetSha = null;
});
- _mergeResult.ShouldBeEquivalentTo(new MergeInfo
+ _mergeResult.Should().BeEquivalentTo(new MergeInfo
{
Message = "Could not merge test into master because of conflicts. Please merge manually",
SourceBranch = "test",
@@ -236,7 +236,7 @@ public void ShouldNotSucceedAndReturnConflicts()
c.TargetSha = null;
});
- _mergeResult.ShouldBeEquivalentTo(new MergeInfo
+ _mergeResult.Should().BeEquivalentTo(new MergeInfo
{
Message = "Could not merge test into master because of conflicts. Please merge manually",
SourceBranch = "test",
diff --git a/Appy.GitDb.Tests/Properties/AssemblyInfo.cs b/Appy.GitDb.Tests/Properties/AssemblyInfo.cs
deleted file mode 100644
index b47b640..0000000
--- a/Appy.GitDb.Tests/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-using System.Reflection;
-using System.Runtime.InteropServices;
-using Xunit;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("Appy.GitDb.Tests")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("AppyParking")]
-[assembly: AssemblyProduct("Appy.GitDb.Tests")]
-[assembly: AssemblyCopyright("Copyright © 2016")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("1c2d86c4-8cad-457e-b4f1-86a5523b3112")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
-[assembly: CollectionBehavior(DisableTestParallelization = true)]
\ No newline at end of file
diff --git a/Appy.GitDb.Tests/Rebasing.cs b/Appy.GitDb.Tests/Rebasing.cs
index bf60b93..4452a3d 100644
--- a/Appy.GitDb.Tests/Rebasing.cs
+++ b/Appy.GitDb.Tests/Rebasing.cs
@@ -62,7 +62,7 @@ async Task removeItems(string branch, int start, int count)
[Fact]
public void RebaseShouldSuccedWithValidInfo() =>
- _rebaseResult.ShouldBeEquivalentTo(RebaseInfo.Succeeded("test", "master", Repo.Branches["test"].Tip.Sha));
+ _rebaseResult.Should().BeEquivalentTo(RebaseInfo.Succeeded("test", "master", Repo.Branches["test"].Tip.Sha));
[Fact]
public async Task AddsTheCorrectFilesToTheBranch() =>
@@ -100,7 +100,7 @@ protected override async Task Because()
[Fact]
public void RebaseShouldSuccedWithValidInfo() =>
- _rebaseResult.ShouldBeEquivalentTo(RebaseInfo.Succeeded("test", "master", string.Empty));
+ _rebaseResult.Should().BeEquivalentTo(RebaseInfo.Succeeded("test", "master", string.Empty));
[Fact]
public void DoesNotCreateACommitOnSourceBranch() =>
@@ -152,7 +152,7 @@ public void ShouldNotSucceedAndReturnConflicts()
c.TargetSha = null;
});
- _rebaseResult.ShouldBeEquivalentTo(new RebaseInfo
+ _rebaseResult.Should().BeEquivalentTo(new RebaseInfo
{
Message = "Could not rebase test onto master because of conflicts. Please merge manually",
SourceBranch = "test",
@@ -210,7 +210,7 @@ public void ShouldNotSucceedAndReturnConflicts()
c.TargetSha = null;
});
- _rebaseResult.ShouldBeEquivalentTo(new RebaseInfo
+ _rebaseResult.Should().BeEquivalentTo(new RebaseInfo
{
Message = "Could not rebase test onto master because of conflicts. Please merge manually",
SourceBranch = "test",
diff --git a/Appy.GitDb.Tests/Transactions.cs b/Appy.GitDb.Tests/Transactions.cs
index 9f46ec6..17cac37 100644
--- a/Appy.GitDb.Tests/Transactions.cs
+++ b/Appy.GitDb.Tests/Transactions.cs
@@ -36,7 +36,7 @@ public void CreatesACommitWithTheCorrectAuthor() =>
public void CreatesASingleCommitWithAllKeys() =>
Repo.Branches[Branch].Tip.Tree
.Select(e => new Document { Key = e.Path, Value = ((Blob)e.Target).GetContentText() })
- .ShouldBeEquivalentTo(_docs);
+ .Should().BeEquivalentTo(_docs);
}
public class DeletingItemsFromATransaction : WithRepo
diff --git a/Appy.GitDb.Tests/Utils/WithRepo.cs b/Appy.GitDb.Tests/Utils/WithRepo.cs
index b77497b..b66dc86 100644
--- a/Appy.GitDb.Tests/Utils/WithRepo.cs
+++ b/Appy.GitDb.Tests/Utils/WithRepo.cs
@@ -1,8 +1,9 @@
-using System;
+using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
+using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Appy.GitDb.Core.Interfaces;
@@ -13,7 +14,7 @@
using Appy.GitDb.Server.Auth;
using Appy.GitDb.Watcher;
using LibGit2Sharp;
-using Microsoft.Owin.Testing;
+using Microsoft.AspNetCore.TestHost;
using Xunit;
namespace Appy.GitDb.Tests.Utils
@@ -28,37 +29,42 @@ public abstract class WithRepo : IAsyncLifetime
TestServer _server;
HttpClient _client;
- protected static readonly User Admin = new User {UserName = "admin", Password = "admin", Roles = new[] {"admin", "read", "write"}};
+ protected static readonly User Admin = new User { UserName = "admin", Password = "admin", Roles = new[] { "admin", "read", "write" } };
protected static readonly User ReadOnly = new User { UserName = "readonly", Password = "readonly", Roles = new[] { "read" } };
protected static readonly User WriteOnly = new User { UserName = "writeonly", Password = "writeonly", Roles = new[] { "write" } };
protected static readonly User ReadWrite = new User { UserName = "readwrite", Password = "readwrite", Roles = new[] { "read", "write" } };
-
- protected static readonly User None = new User { UserName = "", Password = "", Roles = new string[0] };
+ protected static readonly User None = new User { UserName = "", Password = "", Roles = Array.Empty() };
- readonly IEnumerable _users = new List {Admin, ReadOnly, WriteOnly, ReadWrite};
+ readonly IEnumerable _users = new List { Admin, ReadOnly, WriteOnly, ReadWrite };
protected virtual Task Because() => Task.CompletedTask;
static void deleteReadOnlyDirectory(string directory)
{
Directory.EnumerateDirectories(directory)
+ .ToList()
.ForEach(deleteReadOnlyDirectory);
- Directory.EnumerateFiles(directory).Select(file => new FileInfo(file) { Attributes = FileAttributes.Normal })
+ Directory.EnumerateFiles(directory)
+ .Select(file => new FileInfo(file) { Attributes = FileAttributes.Normal })
+ .ToList()
.ForEach(fi => fi.Delete());
-
Directory.Delete(directory);
}
protected void WithUser(User user) =>
- _client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes($"{user.UserName}:{user.Password}")));
-
+ _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
+ "Basic",
+ Convert.ToBase64String(Encoding.ASCII.GetBytes($"{user.UserName}:{user.Password}")));
+
public async Task InitializeAsync()
{
- const string url = "http://localhost"; // this is a dummy url, requests are in-memory, not over the network
- var app = App.Create(url, new LocalGitDb(LocalPath, transactionTimeout: TransactionTimeout), _users);
- _server = TestServer.Create(app.Configuration);
- _client = _server.HttpClient;
- WithUser(Admin);
+ const string url = "http://localhost";
+ _server = new TestServer(App.CreateTestBuilder(
+ new LocalGitDb(LocalPath, transactionTimeout: TransactionTimeout),
+ _users));
+ _client = _server.CreateClient();
+ _client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
+ WithUser(Admin);
Subject = new RemoteGitDb(_client);
Repo = new Repository(LocalPath);
await Because();
@@ -73,12 +79,10 @@ public Task DisposeAsync()
return Task.CompletedTask;
}
- // Use this method to inspect the resulting repository
protected void MoveToNormalRepo(string baseDir)
{
if (Directory.Exists(baseDir))
deleteReadOnlyDirectory(baseDir);
-
Repository.Clone(LocalPath, baseDir, new CloneOptions
{
BranchName = "master",
@@ -86,4 +90,4 @@ protected void MoveToNormalRepo(string baseDir)
});
}
}
-}
\ No newline at end of file
+}
diff --git a/Appy.GitDb.Tests/Utils/WithWatcher.cs b/Appy.GitDb.Tests/Utils/WithWatcher.cs
index df6b2c3..de639a8 100644
--- a/Appy.GitDb.Tests/Utils/WithWatcher.cs
+++ b/Appy.GitDb.Tests/Utils/WithWatcher.cs
@@ -50,7 +50,7 @@ await Task.WhenAll(Enumerable.Range(0, 20)
await Subject.Start(new List());
await Because();
- Thread.Sleep(500);
+ Thread.Sleep(2500);
}
public Task DisposeAsync()
diff --git a/Appy.GitDb.Tests/app.config b/Appy.GitDb.Tests/app.config
deleted file mode 100644
index 5b56fa8..0000000
--- a/Appy.GitDb.Tests/app.config
+++ /dev/null
@@ -1,47 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Appy.GitDb.Tests/packages.config b/Appy.GitDb.Tests/packages.config
deleted file mode 100644
index b21a13e..0000000
--- a/Appy.GitDb.Tests/packages.config
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Appy.GitDb.Watcher/Appy.GitDb.Watcher.csproj b/Appy.GitDb.Watcher/Appy.GitDb.Watcher.csproj
index b5a7377..5697b04 100644
--- a/Appy.GitDb.Watcher/Appy.GitDb.Watcher.csproj
+++ b/Appy.GitDb.Watcher/Appy.GitDb.Watcher.csproj
@@ -1,70 +1,13 @@
-
-
-
-
+
+
- Debug
- AnyCPU
- {E3EBA271-650E-4482-BDEA-41F569051B4D}
- Library
- Properties
- Appy.GitDb.Watcher
- Appy.GitDb.Watcher
- v4.6.1
- 512
-
-
+ net10.0
+ 0.9.0
-
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
- ..\packages\LibGit2Sharp.0.26.2\lib\net46\LibGit2Sharp.dll
-
-
- ..\packages\NLog.4.4.9\lib\net45\NLog.dll
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
+
-
-
-
- This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
-
-
-
-
\ No newline at end of file
+
+
diff --git a/Appy.GitDb.Watcher/Properties/AssemblyInfo.cs b/Appy.GitDb.Watcher/Properties/AssemblyInfo.cs
deleted file mode 100644
index e1e0f2c..0000000
--- a/Appy.GitDb.Watcher/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using System.Reflection;
-using System.Runtime.InteropServices;
-
-[assembly: AssemblyTitle("Appy.GitDb.Watcher")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("AppyParking")]
-[assembly: AssemblyProduct("Appy.GitDb.Watcher")]
-[assembly: AssemblyCopyright("Copyright © 2016")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-[assembly: ComVisible(false)]
-
-[assembly: Guid("e3eba271-650e-4482-bdea-41f569051b4d")]
-
-[assembly: AssemblyVersion("0.11.0")]
diff --git a/Appy.GitDb.Watcher/packages.config b/Appy.GitDb.Watcher/packages.config
deleted file mode 100644
index 080ebd8..0000000
--- a/Appy.GitDb.Watcher/packages.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Appy.GitDb.sln b/Appy.GitDb.sln
index b31783b..1c4d529 100644
--- a/Appy.GitDb.sln
+++ b/Appy.GitDb.sln
@@ -57,9 +57,7 @@ Global
{E3EBA271-650E-4482-BDEA-41F569051B4D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E3EBA271-650E-4482-BDEA-41F569051B4D}.Release|Any CPU.Build.0 = Release|Any CPU
{314EE50D-F6E4-4CB6-AB00-22A7258CF8F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {314EE50D-F6E4-4CB6-AB00-22A7258CF8F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{314EE50D-F6E4-4CB6-AB00-22A7258CF8F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {314EE50D-F6E4-4CB6-AB00-22A7258CF8F5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/global.json b/global.json
index d906919..f4407e0 100644
--- a/global.json
+++ b/global.json
@@ -1,5 +1,6 @@
{
"sdk": {
- "version": "2.2.102"
+ "version": "10.0.200",
+ "rollForward": "latestMajor"
}
- }
\ No newline at end of file
+ }