Updates update service even more
This commit is contained in:
34
ASS.Server/Services/GitCredentialService.cs
Normal file
34
ASS.Server/Services/GitCredentialService.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using LibGit2Sharp;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ASS.Server.Services
|
||||
{
|
||||
class GitCredentialService
|
||||
{
|
||||
IConfiguration config;
|
||||
ILogger logger;
|
||||
|
||||
public GitCredentialService(IConfiguration globalConfig, ILogger<GitCredentialService> log)
|
||||
{
|
||||
config = globalConfig;
|
||||
logger = log;
|
||||
}
|
||||
|
||||
public Credentials GetCredentials(string url, string usernameFromUrl, SupportedCredentialTypes types)
|
||||
{
|
||||
var uri = new Uri(url);
|
||||
var cleaned = uri.Authority + uri.PathAndQuery + uri.Fragment;
|
||||
var creds = config.GetSection("Repository:Credentials").GetSection(cleaned);
|
||||
if (!string.IsNullOrEmpty(creds["Username"]) && !string.IsNullOrEmpty(creds["Password"]))
|
||||
{
|
||||
return new UsernamePasswordCredentials() { Username = creds["Username"], Password = creds["Password"] };
|
||||
}
|
||||
logger.LogWarning("Failed to get credentials for '{cleaned}'.", cleaned);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,8 +1,15 @@
|
||||
using ASS.Server.Helpers;
|
||||
using ASS.Server.Extensions;
|
||||
using ASS.Server.Helpers;
|
||||
using Emet.FileSystems;
|
||||
using LibGit2Sharp;
|
||||
using LibGit2Sharp.Handlers;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace ASS.Server.Services
|
||||
@@ -11,19 +18,148 @@ namespace ASS.Server.Services
|
||||
class UpdateService
|
||||
{
|
||||
|
||||
IConfiguration config;
|
||||
|
||||
private IConfiguration config;
|
||||
private IServiceProvider serviceProvider;
|
||||
private string realLivePath;
|
||||
private Repository repo;
|
||||
private ILogger logger;
|
||||
|
||||
public UpdateService(IConfiguration configuration)
|
||||
public UpdateService(IServiceProvider sp, IConfiguration configuration, ILogger<UpdateService> log)
|
||||
{
|
||||
config = configuration;
|
||||
//Emet.FileSystems.FileSystem.ReadLink(GetLiveDirectory());
|
||||
serviceProvider = sp;
|
||||
logger = log;
|
||||
}
|
||||
|
||||
public string GetRpositoryDirectory(params string[] extraPaths) => FileSystemHelper.GetPath(config, extraPaths, "Repo");
|
||||
public string GetOverrideDirectory(params string[] extraPaths) => FileSystemHelper.GetPath(config, extraPaths, "Override");
|
||||
public string GetLiveDirectory(params string[] extraPaths) => FileSystemHelper.GetPath(config, extraPaths, "Live");
|
||||
public string GetRealLiveDirectory(params string[] extraPaths) => throw new NotImplementedException();
|
||||
public string GetStagingDirectory(params string[] extraPaths) => throw new NotImplementedException();
|
||||
public string GetRealLiveDirectory(params string[] extraPaths)
|
||||
{
|
||||
if (string.IsNullOrEmpty(realLivePath))
|
||||
realLivePath = Path.GetFullPath(Path.Combine(GetLiveDirectory(), "..", FileSystem.ReadLink(GetLiveDirectory())));
|
||||
return Path.GetFullPath(Path.Combine(extraPaths.PreAppend(realLivePath)));
|
||||
}
|
||||
|
||||
public string GetStagingDirectory(params string[] extraPaths) => FileSystemHelper.GetPath(config, extraPaths, getStagingName(Path.GetFileName(GetRealLiveDirectory())));
|
||||
private CredentialsHandler getCredentialsHandler() => serviceProvider.GetRequiredService<GitCredentialService>().GetCredentials;
|
||||
private Signature getSignature() => new Signature(config["Repository:Author:Name"] ?? "Aurora Server System", config["Repository:Author:Email"] ?? "ass@aurorastation.org", DateTimeOffset.Now);
|
||||
private string getStagingName(string liveRealName = null)
|
||||
{
|
||||
switch (liveRealName)
|
||||
{
|
||||
case "DM_A":
|
||||
return "DM_B";
|
||||
case "DM_B":
|
||||
return "DM_A";
|
||||
default:
|
||||
return "DM_A";
|
||||
}
|
||||
}
|
||||
|
||||
private void loadRepo()
|
||||
{
|
||||
if (repo != null)
|
||||
return;
|
||||
repo = new Repository(GetRpositoryDirectory());
|
||||
}
|
||||
|
||||
public void InitilizeRepo()
|
||||
{
|
||||
var repoDir = GetRpositoryDirectory();
|
||||
if (Directory.Exists(repoDir))
|
||||
Directory.Delete(repoDir);
|
||||
var cloneOptions = new CloneOptions()
|
||||
{
|
||||
CredentialsProvider = getCredentialsHandler(),
|
||||
RecurseSubmodules = true,
|
||||
};
|
||||
if (!string.IsNullOrEmpty(config["Repository:Branch"]))
|
||||
cloneOptions.BranchName = config["Repository:Branch"];
|
||||
Repository.Clone(config["Repository:URL"], GetRpositoryDirectory(), cloneOptions);
|
||||
}
|
||||
|
||||
public void UpdateRepo()
|
||||
{
|
||||
loadRepo();
|
||||
if (!(repo.Head?.IsTracking ?? false))
|
||||
throw new Exception("Cannot update while not on a tracked branch");
|
||||
Fetch();
|
||||
|
||||
var trackedBranch = repo.Head.TrackedBranch;
|
||||
var originalCommit = repo.Head.Tip;
|
||||
if (repo.Head.Commits.Count(c => c.Sha == trackedBranch.Tip.Sha) != 0)
|
||||
{
|
||||
logger.LogInformation("Repository is up to date");
|
||||
return;
|
||||
}
|
||||
var mergeResult = repo.Merge(trackedBranch, getSignature());
|
||||
switch (mergeResult.Status)
|
||||
{
|
||||
case MergeStatus.FastForward:
|
||||
case MergeStatus.NonFastForward:
|
||||
logger.LogInformation("Repository has been update successfully.");
|
||||
break;
|
||||
case MergeStatus.Conflicts:
|
||||
repo.Reset(ResetMode.Hard, originalCommit);
|
||||
throw new Exception("Merge introduced merge conflicts, please reset and try again.");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// TODO: Stage a update
|
||||
}
|
||||
|
||||
public void CheckoutRepo(string branch = "master", string remote = "origin")
|
||||
{
|
||||
loadRepo();
|
||||
if (repo.Branches[branch] == null)
|
||||
{
|
||||
Fetch(remote);
|
||||
var trackedBranch = repo.Branches[$"{remote}/{branch}"];
|
||||
if (trackedBranch == null)
|
||||
throw new Exception($"Branch '{branch}' is not found localy or on remote '{remote}'.");
|
||||
var newBranch = repo.CreateBranch(branch, trackedBranch.Tip);
|
||||
repo.Branches.Update(newBranch, b => b.TrackedBranch = trackedBranch.CanonicalName);
|
||||
}
|
||||
repo.Reset(ResetMode.Hard, repo.Head.TrackedBranch?.Tip ?? repo.Head.Tip);
|
||||
|
||||
var checkoutOptions = new CheckoutOptions()
|
||||
{
|
||||
CheckoutModifiers = CheckoutModifiers.Force,
|
||||
};
|
||||
Commands.Checkout(repo, branch, checkoutOptions);
|
||||
//repo.Reset(ResetMode.Hard); // TGS has it, but do we need it?
|
||||
UpdateSubmodules();
|
||||
|
||||
// TODO: Stage a update
|
||||
}
|
||||
|
||||
public void Fetch(string remote = "origin")
|
||||
{
|
||||
loadRepo();
|
||||
Fetch(repo.Network.Remotes[remote]);
|
||||
}
|
||||
public void Fetch(Remote remote)
|
||||
{
|
||||
loadRepo();
|
||||
var fetchOptions = new FetchOptions()
|
||||
{
|
||||
Prune = true,
|
||||
CredentialsProvider = getCredentialsHandler()
|
||||
};
|
||||
Commands.Fetch(repo, remote.Name, remote.FetchRefSpecs.Select(X => X.Specification), fetchOptions, "");
|
||||
}
|
||||
|
||||
public void UpdateSubmodules()
|
||||
{
|
||||
var submoduleUpdate = new SubmoduleUpdateOptions
|
||||
{
|
||||
CredentialsProvider = getCredentialsHandler(),
|
||||
Init = true
|
||||
};
|
||||
loadRepo();
|
||||
foreach (var module in repo.Submodules)
|
||||
repo.Submodules.Update(module.Name, submoduleUpdate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user