diff --git a/TGCommandLine/RootCommands.cs b/TGCommandLine/RootCommands.cs index 4a4c6d1e0a..9569273d98 100644 --- a/TGCommandLine/RootCommands.cs +++ b/TGCommandLine/RootCommands.cs @@ -27,22 +27,44 @@ namespace TGCommandLine protected override ExitCode Run(IList parameters) { var gen_cl = parameters.Count > 1 && parameters[1].ToLower() == "--cl"; - TGRepoUpdateMethod method; + var Repo = Server.GetComponent(); switch (parameters[0].ToLower()) { case "hard": - method = TGRepoUpdateMethod.Hard; + var res = Repo.Update(true); + if (res != null) + { + OutputProc(res); + return ExitCode.ServerError; + } break; case "merge": - method = TGRepoUpdateMethod.Merge; + res = Repo.Update(false); + if (res != null) + { + OutputProc(res); + return ExitCode.ServerError; + } break; default: OutputProc("Please specify hard or merge"); return ExitCode.BadCommand; } - var result = Server.GetComponent().UpdateServer(method, gen_cl); - OutputProc(result ?? "Compilation started!"); - return result == null ? ExitCode.Normal : ExitCode.ServerError; + if (gen_cl) + { + var res = Repo.GenerateChangelog(out string error2); + if (res != null) + OutputProc(res); + else + { + res = Repo.PushChangelog(); + if (res != null) + OutputProc(res); + } + } + var resu = Server.GetComponent().Compile(true); + OutputProc(resu ? "Compilation started!" : "Compilation could not be started!"); + return resu ? ExitCode.Normal : ExitCode.ServerError; } public override string GetArgumentString() @@ -77,9 +99,22 @@ namespace TGCommandLine OutputProc("Invalid tesmerge #: " + parameters[0]); return ExitCode.BadCommand; } - var result = Server.GetComponent().UpdateServer(TGRepoUpdateMethod.None, false, tm); - OutputProc(result ?? "Compilation started!"); - return result == null ? ExitCode.Normal : ExitCode.ServerError; + var Repo = Server.GetComponent(); + var res = Repo.MergePullRequest(tm); + if (res != null) + { + OutputProc(res); + return ExitCode.ServerError; + } + res = Repo.GenerateChangelog(out string error2); + if (res != null) + { + OutputProc(res); + return ExitCode.ServerError; + } + var resu = Server.GetComponent().Compile(true); + OutputProc(resu ? "Compilation started!" : "Compilation could not be started!"); + return resu ? ExitCode.Normal : ExitCode.ServerError; } public override string GetArgumentString() { diff --git a/TGControlPanel/ServerPage.cs b/TGControlPanel/ServerPage.cs index 97cf19924a..4dd2efce03 100644 --- a/TGControlPanel/ServerPage.cs +++ b/TGControlPanel/ServerPage.cs @@ -17,7 +17,7 @@ namespace TGControlPanel } FullUpdateAction fuAction; - int testmergePR; + ushort testmergePR; string updateError; bool updatingFields = false; @@ -246,7 +246,7 @@ namespace TGControlPanel Server.GetComponent().SetPort((ushort)PortSelector.Value); } - private void RunServerUpdate(FullUpdateAction fua, int tm = 0) + private void RunServerUpdate(FullUpdateAction fua, ushort tm = 0) { if (FullUpdateWorker.IsBusy) return; @@ -373,25 +373,67 @@ namespace TGControlPanel return; Server.GetComponent().RequestRestart(); } + + private void FullUpdateWorker_DoWork(object sender, DoWorkEventArgs e) { - var Updater = Server.GetComponent(); + var Repo = Server.GetComponent(); + var DM = Server.GetComponent(); switch (fuAction) { case FullUpdateAction.Testmerge: - updateError = Updater.UpdateServer(TGRepoUpdateMethod.None, false, (ushort)testmergePR); + updateError = Repo.MergePullRequest(testmergePR); + if (updateError == null) + { + updateError = Repo.GenerateChangelog(out string error2); + updateError = DM.Compile(true) ? updateError : "Compilation failed!"; + } break; case FullUpdateAction.UpdateHard: - updateError = Updater.UpdateServer(TGRepoUpdateMethod.Hard, true); + updateError = Repo.Update(true); + if (updateError == null) + { + updateError = Repo.GenerateChangelog(out string error2) ?? Repo.PushChangelog(); + error2 = DM.Compile(true) ? null : "Compilation failed!"; + if(error2 != null) + updateError = error2; + } break; case FullUpdateAction.UpdateHardTestmerge: - updateError = Updater.UpdateServer(TGRepoUpdateMethod.Hard, true, (ushort)testmergePR); + updateError = Repo.Update(true); + if (updateError == null) + { + updateError = Repo.GenerateChangelog(out string error2) ?? Repo.PushChangelog(); + error2 = Repo.MergePullRequest(testmergePR); + if (error2 == null) + { + error2 = Repo.GenerateChangelog(out error2); + error2 = DM.Compile(true) ? error2 : "Compilation failed!"; + } + updateError = error2 ?? updateError; + } break; case FullUpdateAction.UpdateMerge: - updateError = Updater.UpdateServer(TGRepoUpdateMethod.Merge, true, (ushort)testmergePR); + updateError = Repo.Update(false); + if (updateError == null) + { + updateError = Repo.GenerateChangelog(out string error2); + if(updateError == null) + Repo.PushChangelog(); //not an error 99% of the time if this fails, just a dirty tree + error2 = DM.Compile(true) ? null : "Compilation failed!"; + if (error2 != null) + updateError = error2; + } break; case FullUpdateAction.Reset: - updateError = Updater.UpdateServer(TGRepoUpdateMethod.Reset, false, 0); + updateError = Repo.Reset(true); + if (updateError == null) + { + updateError = Repo.GenerateChangelog(out string error2); + error2 = DM.Compile(true) ? null : "Compilation failed!"; + if (error2 != null) + updateError = error2; + } break; } } @@ -407,7 +449,7 @@ namespace TGControlPanel private void UpdateTestmergeButton_Click(object sender, System.EventArgs e) { - RunServerUpdate(FullUpdateAction.UpdateHardTestmerge, (int)ServerTestmergeInput.Value); + RunServerUpdate(FullUpdateAction.UpdateHardTestmerge, (ushort)ServerTestmergeInput.Value); } private void UpdateMergeButton_Click(object sender, System.EventArgs e) @@ -416,7 +458,7 @@ namespace TGControlPanel } private void TestmergeButton_Click(object sender, System.EventArgs e) { - RunServerUpdate(FullUpdateAction.Testmerge, (int)ServerTestmergeInput.Value); + RunServerUpdate(FullUpdateAction.Testmerge, (ushort)ServerTestmergeInput.Value); } private void NudgePortSelector_ValueChanged(object sender, EventArgs e) diff --git a/TGServerService/InterfaceBase.cs b/TGServerService/InterfaceBase.cs index e8ecc903ff..91d23b953c 100644 --- a/TGServerService/InterfaceBase.cs +++ b/TGServerService/InterfaceBase.cs @@ -9,7 +9,7 @@ namespace TGServerService //this line basically says make one instance of the service, use it multithreaded for requests, and never delete it [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)] - partial class TGStationServer : IDisposable, ITGSService, ITGServerUpdater + partial class TGStationServer : IDisposable, ITGSService { //call partial constructors/destructors from here @@ -32,59 +32,12 @@ namespace TGServerService DisposeChat(); } + //public api public string Version() { return TGServerService.Version; } - //one stop update - public string UpdateServer(TGRepoUpdateMethod updateType, bool push_changelog_if_enabled, ushort testmerge_pr) - { - try - { - string res; - switch (updateType) - { - case TGRepoUpdateMethod.Hard: - case TGRepoUpdateMethod.Merge: - res = Update(updateType == TGRepoUpdateMethod.Hard); - if (res != null && res != RepoErrorUpToDate) - return res; - break; - case TGRepoUpdateMethod.Reset: - res = Reset(true); - if (res != null) - return res; - break; - case TGRepoUpdateMethod.None: - break; - } - - if (testmerge_pr != 0) - { - res = MergePullRequestImpl(testmerge_pr, true); - if (res != null && res != RepoErrorUpToDate) - return res; - } - - GenerateChangelog(out res); - if (res == null && push_changelog_if_enabled && SSHAuth()) - { - res = Commit(); - if (res == null) - res = Push(); - } - - if (!Compile(true)) - return "Compilation could not be started!"; - return res; - } - catch (Exception e) - { - return e.ToString(); - } - } - //public api public void VerifyConnection() { } diff --git a/TGServerService/Repository.cs b/TGServerService/Repository.cs index c5f98a172a..1ad74c8522 100644 --- a/TGServerService/Repository.cs +++ b/TGServerService/Repository.cs @@ -671,7 +671,30 @@ namespace TGServerService } } - //public api + public string PushChangelog() + { + return LocalIsRemote() ? Commit() ?? Push() : "Can't push changelog: HEAD does not match tracked remote branch"; + } + + bool LocalIsRemote() + { + lock (RepoLock) + { + if (LoadRepo() != null) + return false; + var R = Repo.Network.Remotes["origin"]; + try + { + Commands.Fetch(Repo, R.Name, R.FetchRefSpecs.Select(X => X.Specification), null, null); + return Repo.Head.IsTracking && Repo.Head.TrackedBranch.Tip.Sha == Repo.Head.Tip.Sha; + } + catch + { + return false; + } + } + } + string Commit() { lock (RepoLock) diff --git a/TGServiceInterface/Repository.cs b/TGServiceInterface/Repository.cs index f853ef1004..ac69f3bd85 100644 --- a/TGServiceInterface/Repository.cs +++ b/TGServiceInterface/Repository.cs @@ -187,6 +187,12 @@ namespace TGServiceInterface [OperationContract] string GenerateChangelog(out string error); + /// + /// Pushes the changelog to the currently git, this operation will only run if the changelog is the only difference to be pushed (i.e. no PRs merged) + /// + /// null on success, error on failure + string PushChangelog(); + /// /// Sets the path to the python 2.7 installation /// diff --git a/TGServiceInterface/Server.cs b/TGServiceInterface/Server.cs index 0a88927638..3270b8dfc5 100644 --- a/TGServiceInterface/Server.cs +++ b/TGServiceInterface/Server.cs @@ -8,7 +8,7 @@ namespace TGServiceInterface /// /// List of types that can be used with GetComponen /// - public static readonly IList ValidInterfaces = new List { typeof(ITGByond), typeof(ITGChat), typeof(ITGCompiler), typeof(ITGConfig), typeof(ITGDreamDaemon), typeof(ITGRepository), typeof(ITGServerUpdater), typeof(ITGSService) }; + public static readonly IList ValidInterfaces = new List { typeof(ITGByond), typeof(ITGChat), typeof(ITGCompiler), typeof(ITGConfig), typeof(ITGDreamDaemon), typeof(ITGRepository), typeof(ITGSService) }; /// /// Base name of the communication pipe @@ -79,45 +79,4 @@ namespace TGServiceInterface [OperationContract] string Version(); } - - /// - /// How to modify the repo during the UpdateServer operation - /// - public enum TGRepoUpdateMethod - { - /// - /// Do not update the repo - /// - None, - /// - /// Update the repo by merging the origin branch - /// - Merge, - /// - /// Update the repo by hard resetting to the remote branch - /// - Hard, - /// - /// Clean the repo by hard resetting to the origin branch - /// - Reset, - } - - /// - /// One stop shop for server updates - /// - [ServiceContract] - public interface ITGServerUpdater - { - /// - /// Updates the server fully with various options as a blocking operation - /// - /// How to handle the repository during the update - /// true if the changelog should be pushed to git - /// If not zero, will testmerge the designated pull request - /// null on success, error message on failure - [OperationContract] - string UpdateServer(TGRepoUpdateMethod updateType, bool push_changelog_if_enabled, ushort testmerge_pr = 0); - } - }