Merge pull request #215 from Cyberboss/CompileGates

Compilation is blocked if TGS3.json changes. Adds command/button to update it
This commit is contained in:
Jordan Brown
2017-09-27 12:30:17 -04:00
committed by GitHub
8 changed files with 230 additions and 95 deletions
+25 -1
View File
@@ -9,7 +9,7 @@ namespace TGCommandLine
public RepoCommand()
{
Keyword = "repo";
Children = new Command[] { new RepoSetupCommand(), new RepoUpdateCommand(), new RepoGenChangelogCommand(), new RepoPushChangelogCommand(), new RepoPythonPathCommand(), new RepoSetEmailCommand(), new RepoSetNameCommand(), new RepoMergePRCommand(), new RepoListPRsCommand(), new RepoStatusCommand(), new RepoListBackupsCommand(), new RepoCheckoutCommand(), new RepoResetCommand() };
Children = new Command[] { new RepoSetupCommand(), new RepoUpdateCommand(), new RepoGenChangelogCommand(), new RepoPushChangelogCommand(), new RepoPythonPathCommand(), new RepoSetEmailCommand(), new RepoSetNameCommand(), new RepoMergePRCommand(), new RepoListPRsCommand(), new RepoStatusCommand(), new RepoListBackupsCommand(), new RepoCheckoutCommand(), new RepoResetCommand(), new RepoUpdateJsonCommand() };
}
public override string GetHelpText()
{
@@ -17,6 +17,30 @@ namespace TGCommandLine
}
}
class RepoUpdateJsonCommand : Command
{
public RepoUpdateJsonCommand()
{
Keyword = "update-json";
}
public override string GetHelpText()
{
return "Updates the cached TGS3.json with the one from the repo. Compilation is blocked if these two do not match.";
}
protected override ExitCode Run(IList<string> parameters)
{
var res = Server.GetComponent<ITGRepository>().UpdateTGS3Json();
if (res != null)
{
OutputProc(res);
return ExitCode.ServerError;
}
return ExitCode.Normal;
}
}
class RepoSetupCommand : Command
{
public RepoSetupCommand()
+16 -1
View File
@@ -158,6 +158,7 @@
this.StaticFileCreateButton = new System.Windows.Forms.Button();
this.label6 = new System.Windows.Forms.Label();
this.StaticFileListBox = new System.Windows.Forms.ListBox();
this.TGSJsonUpdate = new System.Windows.Forms.Button();
this.ChatPanel.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.ChatPortSelector)).BeginInit();
this.ChatProviderSelectorPanel.SuspendLayout();
@@ -1279,6 +1280,7 @@
// RepoPanel
//
this.RepoPanel.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(39)))), ((int)(((byte)(40)))), ((int)(((byte)(34)))));
this.RepoPanel.Controls.Add(this.TGSJsonUpdate);
this.RepoPanel.Controls.Add(this.RepoRefreshButton);
this.RepoPanel.Controls.Add(this.BackupTagsList);
this.RepoPanel.Controls.Add(this.ResetRemote);
@@ -1349,7 +1351,7 @@
// RecloneButton
//
this.RecloneButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.RecloneButton.Location = new System.Drawing.Point(722, 212);
this.RecloneButton.Location = new System.Drawing.Point(722, 247);
this.RecloneButton.Name = "RecloneButton";
this.RecloneButton.Size = new System.Drawing.Size(140, 29);
this.RecloneButton.TabIndex = 32;
@@ -1734,6 +1736,18 @@
this.StaticFileListBox.TabIndex = 0;
this.StaticFileListBox.SelectedIndexChanged += new System.EventHandler(this.StaticFileListBox_SelectedIndexChanged);
//
// TGSJsonUpdate
//
this.TGSJsonUpdate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.TGSJsonUpdate.Location = new System.Drawing.Point(722, 212);
this.TGSJsonUpdate.Name = "TGSJsonUpdate";
this.TGSJsonUpdate.Size = new System.Drawing.Size(140, 29);
this.TGSJsonUpdate.TabIndex = 36;
this.TGSJsonUpdate.Text = "Update TGS3.json";
this.TGSJsonUpdate.UseVisualStyleBackColor = true;
this.TGSJsonUpdate.Visible = false;
this.TGSJsonUpdate.Click += new System.EventHandler(this.TGSJsonUpdate_Click);
//
// Main
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@@ -1899,5 +1913,6 @@
private System.Windows.Forms.Button StaticFileSaveButton;
private System.Windows.Forms.Button StaticFilesRefreshButton;
private System.Windows.Forms.Button StaticFileDownloadButton;
private System.Windows.Forms.Button TGSJsonUpdate;
}
}
-1
View File
@@ -29,6 +29,5 @@ namespace TGControlPanel
{
Properties.Settings.Default.LastPageIndex = Panels.SelectedIndex;
}
}
}
+11
View File
@@ -115,6 +115,7 @@ namespace TGControlPanel
RepoGenChangelogButton.Visible = true;
RecloneButton.Visible = true;
ResetRemote.Visible = true;
TGSJsonUpdate.Visible = true;
CurrentRevisionLabel.Text = Repo.GetHead(false, out string error) ?? "Unknown";
RepoRemoteTextBox.Text = Repo.GetRemote(out error) ?? "Unknown";
@@ -262,6 +263,7 @@ namespace TGControlPanel
ResetRemote.Visible = false;
BackupTagsList.Visible = false;
RepoRefreshButton.Visible = false;
TGSJsonUpdate.Visible = false;
RepoPanel.UseWaitCursor = true;
@@ -345,5 +347,14 @@ namespace TGControlPanel
{
DoAsyncOp(RepoAction.GenCL, "Generating changelog...");
}
private void TGSJsonUpdate_Click(object sender, EventArgs e)
{
if (MessageBox.Show("This will update the cached TGS3.json to the current repository version, potentially redefining symlinks. Proceed?", "Json Update", MessageBoxButtons.YesNo) != DialogResult.Yes)
return;
var res = Server.GetComponent<ITGRepository>().UpdateTGS3Json();
if (res != null)
MessageBox.Show(res);
}
}
}
+70 -52
View File
@@ -172,6 +172,16 @@ namespace TGServerService
return;
}
}
if (!RepoConfigsMatch())
{
lock (CompilerLock)
{
lastCompilerError = "Repository TGS3.json does not match cached version! Please update the config appropriately!";
compilerCurrentStatus = IsInitialized();
return;
}
}
try
{
SendMessage("DM: Setting up symlinks...", ChatMessageType.DeveloperInfo);
@@ -181,7 +191,7 @@ namespace TGServerService
Directory.CreateDirectory(GameDirA);
Directory.CreateDirectory(GameDirB);
var Config = LoadRepoConfig();
var Config = new RepoConfig(false);
if (Config != null) {
foreach (var I in Config.StaticDirectoryPaths)
@@ -287,52 +297,23 @@ namespace TGServerService
{
if (GetVersion(TGByondVersion.Installed) == null)
{
lastCompilerError = "BYOND not installed!";
compilerCurrentStatus = TGCompilerStatus.Initialized;
return;
}
bool silent;
lock (CompilerLock)
{
silent = silentCompile;
silentCompile = false;
}
if(!silent)
SendMessage("DM: Compiling...", ChatMessageType.DeveloperInfo);
var resurrectee = GetStagingDir();
var Config = LoadRepoConfig();
var deleteExcludeList = new List<string>();
if (Config != null)
{
deleteExcludeList.AddRange(Config.StaticDirectoryPaths);
deleteExcludeList.AddRange(Config.DLLPaths);
Program.DeleteDirectory(resurrectee, true, deleteExcludeList);
}
Directory.CreateDirectory(resurrectee + "/.git/logs");
if (Config != null)
{
foreach (var I in Config.StaticDirectoryPaths)
lock (CompilerLock)
{
var the_path = Path.Combine(resurrectee, I);
if (!Directory.Exists(the_path))
CreateSymlink(Path.Combine(resurrectee, I), Path.Combine(StaticDirs, I));
}
foreach (var I in Config.DLLPaths)
{
var the_path = Path.Combine(resurrectee, I);
if (!File.Exists(the_path))
CreateSymlink(the_path, Path.Combine(StaticDirs, I));
lastCompilerError = "BYOND not installed!";
compilerCurrentStatus = TGCompilerStatus.Initialized;
return;
}
}
if (!File.Exists(Path.Combine(resurrectee, InterfaceDLLName)))
CreateSymlink(Path.Combine(resurrectee, InterfaceDLLName), InterfaceDLLName);
if (!RepoConfigsMatch())
{
lock (CompilerLock)
{
lastCompilerError = "Repository TGS3.json does not match cached version! Please update the config appropriately!";
compilerCurrentStatus = IsInitialized();
return;
}
}
string resurrectee;
bool repobusy_check = false;
if (!Monitor.TryEnter(RepoLock))
repobusy_check = true;
@@ -352,12 +333,49 @@ namespace TGServerService
lock (CompilerLock)
{
lastCompilerError = "The repo could not be locked for copying";
compilerCurrentStatus = TGCompilerStatus.Initialized; //still fairly valid
compilerCurrentStatus = TGCompilerStatus.Initialized; //still fairly valid
return;
}
}
try
{
bool silent;
lock (CompilerLock)
{
silent = silentCompile;
silentCompile = false;
}
if (!silent)
SendMessage("DM: Compiling...", ChatMessageType.DeveloperInfo);
resurrectee = GetStagingDir();
var Config = new RepoConfig(false);
var deleteExcludeList = new List<string>();
deleteExcludeList.AddRange(Config.StaticDirectoryPaths);
deleteExcludeList.AddRange(Config.DLLPaths);
Program.DeleteDirectory(resurrectee, true, deleteExcludeList);
Directory.CreateDirectory(resurrectee + "/.git/logs");
foreach (var I in Config.StaticDirectoryPaths)
{
var the_path = Path.Combine(resurrectee, I);
if (!Directory.Exists(the_path))
CreateSymlink(Path.Combine(resurrectee, I), Path.Combine(StaticDirs, I));
}
foreach (var I in Config.DLLPaths)
{
var the_path = Path.Combine(resurrectee, I);
if (!File.Exists(the_path))
CreateSymlink(the_path, Path.Combine(StaticDirs, I));
}
if (!File.Exists(Path.Combine(resurrectee, InterfaceDLLName)))
CreateSymlink(Path.Combine(resurrectee, InterfaceDLLName), InterfaceDLLName);
deleteExcludeList.Add(".git");
Program.CopyDirectory(RepoPath, resurrectee, deleteExcludeList);
//just the tip
@@ -376,9 +394,9 @@ namespace TGServerService
RepoBusy = false;
}
}
var res = CreateBackup();
if(res != null)
if (res != null)
lock (CompilerLock)
{
lastCompilerError = res;
@@ -387,7 +405,7 @@ namespace TGServerService
}
var dmeName = ProjectName() + ".dme";
var dmePath = resurrectee + "/" + dmeName;
var dmePath = resurrectee + "/" + dmeName;
if (!File.Exists(dmePath))
{
var errorMsg = String.Format("Could not find {0}!", dmeName);
@@ -417,7 +435,7 @@ namespace TGServerService
DM.StartInfo.UseShellExecute = false;
var OutputList = new StringBuilder();
DM.OutputDataReceived += new DataReceivedEventHandler(
delegate(object sender, DataReceivedEventArgs e)
delegate (object sender, DataReceivedEventArgs e)
{
OutputList.Append(Environment.NewLine);
OutputList.Append(e.Data);
@@ -431,7 +449,7 @@ namespace TGServerService
return;
canCancelCompilation = true;
}
DM.Start();
DM.BeginOutputReadLine();
while (!DM.HasExited)
@@ -469,7 +487,7 @@ namespace TGServerService
{
//gotta go fast
var online = currentStatus == TGDreamDaemonStatus.Online;
if(online)
if (online)
Proc.Suspend();
try
{
@@ -480,7 +498,7 @@ namespace TGServerService
}
finally
{
if(online && !Proc.HasExited)
if (online && !Proc.HasExited)
Proc.Resume();
}
}
+1 -1
View File
@@ -33,7 +33,7 @@ namespace TGServerService
if (repo)
{
//ensure we aren't trying to read anything outside the static dirs
var Config = LoadRepoConfig();
var Config = new RepoConfig(false);
if (Config == null)
{
error = "Unable to load static directory configuration";
+99 -39
View File
@@ -15,6 +15,7 @@ namespace TGServerService
{
const string RepoPath = "Repository";
const string RepoTGS3SettingsPath = RepoPath + "/TGS3.json";
const string CachedTGS3SettingsPath = "TGS3.json";
const string RepoErrorUpToDate = "Already up to date!";
const string SSHPushRemote = "ssh_push_target";
const string PrivateKeyPath = "RepoKey/private_key.txt";
@@ -33,20 +34,22 @@ namespace TGServerService
/// Repo specific information about the installation
/// Requires RepoLock and !RepoBusy to be instantiated
/// </summary>
class RepoConfig
class RepoConfig : IEquatable<RepoConfig>
{
IList<string> LoadArray(object o) {
var array = (object[])o;
var res = new List<string>();
foreach (var I in array)
res.Add((string)I);
return res;
}
public RepoConfig()
public readonly bool ChangelogSupport;
public readonly string PathToChangelogPy;
public readonly string ChangelogPyArguments;
public readonly IList<string> PipDependancies = new List<string>();
public readonly IList<string> ChangelogPathsToStage = new List<string>();
public readonly IList<string> StaticDirectoryPaths = new List<string>();
public readonly IList<string> DLLPaths = new List<string>();
public RepoConfig(bool FromRepository)
{
if (!File.Exists(RepoTGS3SettingsPath))
var path = FromRepository ? RepoTGS3SettingsPath : CachedTGS3SettingsPath;
if (!File.Exists(path))
return;
var rawdata = File.ReadAllText(RepoTGS3SettingsPath);
var rawdata = File.ReadAllText(path);
var Deserializer = new JavaScriptSerializer();
var json = Deserializer.Deserialize<IDictionary<string, object>>(rawdata);
try
@@ -80,16 +83,59 @@ namespace TGServerService
}
catch { }
}
public readonly bool ChangelogSupport;
public readonly string PathToChangelogPy;
public readonly string ChangelogPyArguments;
public readonly IList<string> PipDependancies = new List<string>();
public readonly IList<string> ChangelogPathsToStage = new List<string>();
public readonly IList<string> StaticDirectoryPaths = new List<string>();
public readonly IList<string> DLLPaths = new List<string>();
}
private static IList<string> LoadArray(object o)
{
var array = (object[])o;
var res = new List<string>();
foreach (var I in array)
res.Add((string)I);
return res;
}
RepoConfig _CurrentRepoConfig;
public override bool Equals(object obj)
{
return Equals(obj as RepoConfig);
}
private static bool ListEquals(IList<string> A, IList<string> B)
{
return A.All(B.Contains) && A.Count == B.Count;
}
public bool Equals(RepoConfig other)
{
return ChangelogSupport == other.ChangelogSupport
&& PathToChangelogPy == other.PathToChangelogPy
&& ChangelogPyArguments == other.ChangelogPyArguments
&& ListEquals(PipDependancies, other.PipDependancies)
&& ListEquals(ChangelogPathsToStage, other.ChangelogPathsToStage)
&& ListEquals(StaticDirectoryPaths, other.StaticDirectoryPaths)
&& ListEquals(DLLPaths, other.DLLPaths);
}
public override int GetHashCode()
{
var hashCode = 1890628544;
hashCode = hashCode * -1521134295 + ChangelogSupport.GetHashCode();
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(PathToChangelogPy);
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(ChangelogPyArguments);
hashCode = hashCode * -1521134295 + EqualityComparer<IList<string>>.Default.GetHashCode(PipDependancies);
hashCode = hashCode * -1521134295 + EqualityComparer<IList<string>>.Default.GetHashCode(ChangelogPathsToStage);
hashCode = hashCode * -1521134295 + EqualityComparer<IList<string>>.Default.GetHashCode(StaticDirectoryPaths);
hashCode = hashCode * -1521134295 + EqualityComparer<IList<string>>.Default.GetHashCode(DLLPaths);
return hashCode;
}
public static bool operator ==(RepoConfig config1, RepoConfig config2)
{
return EqualityComparer<RepoConfig>.Default.Equals(config1, config2);
}
public static bool operator !=(RepoConfig config1, RepoConfig config2)
{
return !(config1 == config2);
}
}
void InitRepo()
{
@@ -97,19 +143,21 @@ namespace TGServerService
UpdateInterfaceDll(false);
}
RepoConfig LoadRepoConfig()
bool RepoConfigsMatch()
{
if (_CurrentRepoConfig == null)
lock (RepoLock)
{
if (RepoBusy)
return null;
if (LoadRepo() == null)
_CurrentRepoConfig = new RepoConfig();
}
return _CurrentRepoConfig;
//this should never be called while the repo is busy
RepoConfig I = null;
lock (RepoLock)
{
if (!RepoBusy && LoadRepo() == null)
I = new RepoConfig(true);
}
if (I == null)
throw new Exception("Unable to load TGS3.json from repo!");
var J = new RepoConfig(false);
return I == J;
}
//public api
public bool OperationInProgress()
{
@@ -261,11 +309,28 @@ namespace TGServerService
}
}
public string UpdateTGS3Json()
{
try
{
if (File.Exists(RepoTGS3SettingsPath))
File.Copy(RepoTGS3SettingsPath, CachedTGS3SettingsPath, true);
else if (File.Exists(CachedTGS3SettingsPath))
File.Delete(CachedTGS3SettingsPath);
}
catch(Exception e)
{
return e.ToString();
}
return null;
}
void InitialConfigureRepository()
{
Directory.CreateDirectory(StaticDirs);
UpdateInterfaceDll(false);
var Config = new RepoConfig(); //RepoBusy is set if we're here
UpdateTGS3Json();
var Config = new RepoConfig(false); //RepoBusy is set if we're here
foreach(var I in Config.StaticDirectoryPaths)
{
try
@@ -300,7 +365,6 @@ namespace TGServerService
TGServerService.WriteWarning("Could not setup static DLL: " + I, TGServerService.EventID.RepoConfigurationFail);
}
}
_CurrentRepoConfig = Config;
}
//kicks off the cloning thread
@@ -442,7 +506,6 @@ namespace TGServerService
Commands.Checkout(Repo, sha, Opts);
var res = ResetNoLock(null);
UpdateSubmodules();
_CurrentRepoConfig = new RepoConfig();
SendMessage("REPO: Checkout complete!", ChatMessageType.DeveloperInfo);
TGServerService.WriteInfo("Repo checked out " + sha, TGServerService.EventID.RepoCheckout);
return res;
@@ -510,7 +573,6 @@ namespace TGServerService
if (res != null)
throw new Exception(res);
UpdateSubmodules();
_CurrentRepoConfig = new RepoConfig();
TGServerService.WriteInfo("Repo merge updated to " + originBranch.Tip.Sha, TGServerService.EventID.RepoMergeUpdate);
return null;
}
@@ -617,7 +679,6 @@ namespace TGServerService
lock (RepoLock)
{
var res = LoadRepo() ?? ResetNoLock(trackedBranch ? (Repo.Head.TrackedBranch ?? Repo.Head) : Repo.Head);
_CurrentRepoConfig = new RepoConfig();
if (res == null)
{
SendMessage(String.Format("REPO: Hard reset to {0}branch", trackedBranch ? "tracked " : ""), ChatMessageType.DeveloperInfo);
@@ -725,7 +786,6 @@ namespace TGServerService
if (Result == null)
try
{
_CurrentRepoConfig = new RepoConfig();
UpdateSubmodules();
}
catch (Exception e)
@@ -849,7 +909,7 @@ namespace TGServerService
public string PushChangelog()
{
var Config = LoadRepoConfig();
var Config = new RepoConfig(false);
if (Config == null)
return "Error reading changelog configuration";
if(!Config.ChangelogSupport || !SSHAuth())
@@ -1003,7 +1063,7 @@ namespace TGServerService
//impl proc just for single level recursion
public string GenerateChangelogImpl(out string error, bool recurse = false)
{
var RConfig = LoadRepoConfig();
var RConfig = new RepoConfig(false);
if (RConfig == null)
{
error = null;
+8
View File
@@ -217,5 +217,13 @@ namespace TGServiceInterface
/// <returns>A dictionary of tag name -> commit on success, null on failure</returns>
[OperationContract]
IDictionary<string, string> ListBackups(out string error);
/// <summary>
/// Updates the cached TGS3.json to the repo's version
/// Compiles will not succeed if these two to not match
/// </summary>
/// <returns>null on success, error message on failure</returns>
[OperationContract]
string UpdateTGS3Json();
}
}