mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-27 07:04:57 +01:00
Sanely namespaces the project
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using TGS.Interface;
|
||||
using TGS.Interface.Components;
|
||||
|
||||
namespace TGS.ControlPanel
|
||||
{
|
||||
partial class ControlPanel
|
||||
{
|
||||
string lastReadError = null;
|
||||
void InitBYONDPage()
|
||||
{
|
||||
var BYOND = Interface.GetComponent<ITGByond>();
|
||||
var CV = BYOND.GetVersion(ByondVersion.Installed);
|
||||
if (CV == null)
|
||||
CV = BYOND.GetVersion(ByondVersion.Staged);
|
||||
if (CV != null)
|
||||
{
|
||||
var splits = CV.Split('.');
|
||||
if(splits.Length == 2)
|
||||
{
|
||||
try
|
||||
{
|
||||
var Major = Convert.ToInt32(splits[0]);
|
||||
var Minor = Convert.ToInt32(splits[1]);
|
||||
MajorVersionNumeric.Value = Major;
|
||||
MinorVersionNumeric.Value = Minor;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
var latestVer = BYOND.GetVersion(ByondVersion.Latest);
|
||||
LatestVersionLabel.Text = latestVer;
|
||||
|
||||
try
|
||||
{
|
||||
var splits = latestVer.Split('.');
|
||||
var maj = Convert.ToInt32(splits[0]);
|
||||
MinorVersionNumeric.Value = Convert.ToInt32(splits[1]);
|
||||
MajorVersionNumeric.Value = maj;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
private void UpdateButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
UpdateBYONDButtons();
|
||||
if (!Interface.GetComponent<ITGByond>().UpdateToVersion((int)MajorVersionNumeric.Value, (int)MinorVersionNumeric.Value))
|
||||
MessageBox.Show("Unable to begin update, there is another operation in progress.");
|
||||
}
|
||||
|
||||
private void BYONDRefreshButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
UpdateBYONDButtons();
|
||||
}
|
||||
void UpdateBYONDButtons()
|
||||
{
|
||||
var BYOND = Interface.GetComponent<ITGByond>();
|
||||
|
||||
VersionLabel.Text = BYOND.GetVersion(ByondVersion.Installed) ?? "Not Installed";
|
||||
|
||||
StagedVersionTitle.Visible = false;
|
||||
StagedVersionLabel.Visible = false;
|
||||
switch (BYOND.CurrentStatus())
|
||||
{
|
||||
case ByondStatus.Idle:
|
||||
case ByondStatus.Starting:
|
||||
StatusLabel.Text = "Idle";
|
||||
UpdateButton.Enabled = true;
|
||||
break;
|
||||
case ByondStatus.Downloading:
|
||||
StatusLabel.Text = "Downloading...";
|
||||
UpdateButton.Enabled = false;
|
||||
break;
|
||||
case ByondStatus.Staging:
|
||||
StatusLabel.Text = "Staging...";
|
||||
UpdateButton.Enabled = false;
|
||||
break;
|
||||
case ByondStatus.Staged:
|
||||
StagedVersionTitle.Visible = true;
|
||||
StagedVersionLabel.Visible = true;
|
||||
StagedVersionLabel.Text = BYOND.GetVersion(ByondVersion.Staged) ?? "Unknown";
|
||||
StatusLabel.Text = "Staged and waiting for BYOND to shutdown...";
|
||||
UpdateButton.Enabled = true;
|
||||
break;
|
||||
case ByondStatus.Updating:
|
||||
StatusLabel.Text = "Applying update...";
|
||||
UpdateButton.Enabled = false;
|
||||
break;
|
||||
}
|
||||
var error = Interface.GetComponent<ITGByond>().GetError();
|
||||
if (error != lastReadError)
|
||||
{
|
||||
lastReadError = error;
|
||||
if (error != null)
|
||||
MessageBox.Show("An error occurred: " + lastReadError);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Forms;
|
||||
using TGS.Interface;
|
||||
using TGS.Interface.Components;
|
||||
|
||||
namespace TGS.ControlPanel
|
||||
{
|
||||
partial class ControlPanel
|
||||
{
|
||||
bool updatingChat = false;
|
||||
|
||||
ChatProvider ModifyingProvider
|
||||
{
|
||||
get { return (ChatProvider)Properties.Settings.Default.LastChatProvider; }
|
||||
set { Properties.Settings.Default.LastChatProvider = (int)value; }
|
||||
}
|
||||
|
||||
void LoadChatPage()
|
||||
{
|
||||
updatingChat = true;
|
||||
var Chat = Interface.GetComponent<ITGChat>();
|
||||
var PI = Chat.ProviderInfos()[(int)ModifyingProvider];
|
||||
ChatAdminsTextBox.Visible = true;
|
||||
IRCModesComboBox.Visible = false;
|
||||
switch (ModifyingProvider)
|
||||
{
|
||||
case ChatProvider.Discord:
|
||||
var DPI = new DiscordSetupInfo(PI);
|
||||
DiscordProviderSwitch.Select();
|
||||
AuthField1.Text = DPI.BotToken; //it's invisible so whatever
|
||||
AuthField1Title.Text = "Bot Token:";
|
||||
AuthField2.Visible = false;
|
||||
AuthField2Title.Visible = false;
|
||||
ChatServerText.Visible = false;
|
||||
ChatPortSelector.Visible = false;
|
||||
ChatServerTitle.Visible = false;
|
||||
ChatPortTitle.Visible = false;
|
||||
ChatNicknameText.Visible = false;
|
||||
ChatNicknameTitle.Visible = false;
|
||||
|
||||
ChatAdminsTitle.Text = String.Format("Admin {0} IDs:", DPI.AdminsAreSpecial ? "Role" : "User");
|
||||
ChannelsTitle.Text = "Broadcast/Listening Channel IDs:";
|
||||
AdminModeNormal.Text = "User IDs";
|
||||
AdminModeSpecial.Text = "Role IDs";
|
||||
break;
|
||||
case ChatProvider.IRC:
|
||||
var IRC = new IRCSetupInfo(PI);
|
||||
IRCProviderSwitch.Select();
|
||||
AuthField1.Text = IRC.AuthTarget;
|
||||
AuthField2.Text = IRC.AuthMessage;
|
||||
AuthField2.Visible = true;
|
||||
AuthField2Title.Visible = true;
|
||||
AuthField1Title.Text = "Auth Target:";
|
||||
AuthField2Title.Text = "Auth Message:";
|
||||
ChatServerText.Visible = true;
|
||||
ChatPortSelector.Visible = true;
|
||||
ChatServerTitle.Visible = true;
|
||||
ChatPortTitle.Visible = true;
|
||||
ChatServerText.Text = IRC.URL;
|
||||
ChatPortSelector.Value = IRC.Port;
|
||||
ChatNicknameText.Visible = true;
|
||||
ChatNicknameTitle.Visible = true;
|
||||
ChatNicknameText.Text = IRC.Nickname;
|
||||
ChatAdminsTitle.Text = String.Format("Admin {0}:", IRC.AdminsAreSpecial ? "Req Mode" : "Nicknames");
|
||||
ChannelsTitle.Text = "Broadcast/Listening Channels:";
|
||||
AdminModeNormal.Text = "Nicknames";
|
||||
AdminModeSpecial.Text = "Channel Mode";
|
||||
if (IRC.AdminsAreSpecial)
|
||||
{
|
||||
ChatAdminsTextBox.Visible = false;
|
||||
IRCModesComboBox.Visible = true;
|
||||
IRCModesComboBox.SelectedIndex = (int)IRC.AuthLevel;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Properties.Settings.Default.LastChatProvider = (int)ChatProvider.IRC;
|
||||
LoadChatPage();
|
||||
return;
|
||||
}
|
||||
|
||||
AdminModeNormal.Checked = !PI.AdminsAreSpecial;
|
||||
AdminModeSpecial.Checked = PI.AdminsAreSpecial;
|
||||
ChatEnabledCheckbox.Checked = PI.Enabled;
|
||||
if (!PI.Enabled)
|
||||
ChatStatusLabel.Text = "Disabled";
|
||||
else if (Chat.Connected(ModifyingProvider))
|
||||
ChatStatusLabel.Text = "Connected";
|
||||
else
|
||||
ChatStatusLabel.Text = "Disconnected";
|
||||
ChatReconnectButton.Enabled = PI.Enabled;
|
||||
|
||||
AssignListToTextbox(PI.AdminList, ChatAdminsTextBox);
|
||||
AssignListToTextbox(PI.WatchdogChannels, WDChannelsTextbox);
|
||||
AssignListToTextbox(PI.AdminChannels, AdminChannelsTextbox);
|
||||
AssignListToTextbox(PI.DevChannels, DevChannelsTextbox);
|
||||
AssignListToTextbox(PI.GameChannels, GameChannelsTextbox);
|
||||
updatingChat = false;
|
||||
}
|
||||
|
||||
static void AssignListToTextbox(IList<string> a, TextBox b)
|
||||
{
|
||||
b.Text = "";
|
||||
foreach (var I in a)
|
||||
b.Text += I + Environment.NewLine;
|
||||
}
|
||||
|
||||
private void ChatRefreshButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
LoadChatPage();
|
||||
}
|
||||
|
||||
private void ChatReconnectButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
Interface.GetComponent<ITGChat>().Reconnect(ModifyingProvider);
|
||||
LoadChatPage();
|
||||
}
|
||||
|
||||
static string[] SplitByLine(TextBox t)
|
||||
{
|
||||
var channels = t.Text.Split('\n');
|
||||
|
||||
var finalChannels = new List<string>();
|
||||
foreach (var I in channels)
|
||||
{
|
||||
var trimmed = I.Trim();
|
||||
if(trimmed != "")
|
||||
finalChannels.Add(trimmed);
|
||||
}
|
||||
return finalChannels.ToArray();
|
||||
}
|
||||
|
||||
private void DiscordProviderSwitch_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (!updatingChat && DiscordProviderSwitch.Checked)
|
||||
{
|
||||
ModifyingProvider = ChatProvider.Discord;
|
||||
LoadChatPage();
|
||||
}
|
||||
}
|
||||
|
||||
private void IRCProviderSwitch_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (!updatingChat && IRCProviderSwitch.Checked)
|
||||
{
|
||||
ModifyingProvider = ChatProvider.IRC;
|
||||
LoadChatPage();
|
||||
}
|
||||
}
|
||||
void SetAdminsAreSpecial(bool value)
|
||||
{
|
||||
var Chat = Interface.GetComponent<ITGChat>();
|
||||
var PI = Chat.ProviderInfos()[(int)ModifyingProvider];
|
||||
PI.AdminsAreSpecial = value;
|
||||
var res = Chat.SetProviderInfo(PI);
|
||||
if (res != null)
|
||||
MessageBox.Show(res);
|
||||
LoadChatPage();
|
||||
}
|
||||
|
||||
private void AdminModeNormal_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (!updatingChat && AdminModeNormal.Checked)
|
||||
SetAdminsAreSpecial(false);
|
||||
}
|
||||
|
||||
private void AdminModeSpecial_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (!updatingChat && AdminModeSpecial.Checked)
|
||||
SetAdminsAreSpecial(true);
|
||||
}
|
||||
|
||||
private void ChatApplyButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
string res = null;
|
||||
ChatSetupInfo wip = null;
|
||||
switch (ModifyingProvider)
|
||||
{
|
||||
case ChatProvider.Discord:
|
||||
wip = new DiscordSetupInfo()
|
||||
{
|
||||
BotToken = AuthField1.Text
|
||||
};
|
||||
break;
|
||||
case ChatProvider.IRC:
|
||||
wip = new IRCSetupInfo()
|
||||
{
|
||||
AuthMessage = AuthField2.Text,
|
||||
AuthTarget = AuthField1.Text,
|
||||
Nickname = ChatNicknameText.Text,
|
||||
URL = ChatServerText.Text,
|
||||
Port = (ushort)ChatPortSelector.Value,
|
||||
AuthLevel = (IRCMode)IRCModesComboBox.SelectedIndex,
|
||||
};
|
||||
break;
|
||||
default:
|
||||
res = "You really shouldn't be able to read this.";
|
||||
break;
|
||||
}
|
||||
|
||||
if (res == null)
|
||||
{
|
||||
wip.AdminChannels = new List<string>(AdminChannelsTextbox.Text.Split(Environment.NewLine.ToCharArray()));
|
||||
wip.WatchdogChannels = new List<string>(WDChannelsTextbox.Text.Split(Environment.NewLine.ToCharArray()));
|
||||
wip.DevChannels = new List<string>(DevChannelsTextbox.Text.Split(Environment.NewLine.ToCharArray()));
|
||||
wip.GameChannels = new List<string>(GameChannelsTextbox.Text.Split(Environment.NewLine.ToCharArray()));
|
||||
wip.AdminList = new List<string>(ChatAdminsTextBox.Text.Split(Environment.NewLine.ToCharArray()));
|
||||
wip.Enabled = ChatEnabledCheckbox.Checked;
|
||||
wip.AdminsAreSpecial = AdminModeSpecial.Checked;
|
||||
|
||||
res = Interface.GetComponent<ITGChat>().SetProviderInfo(wip);
|
||||
}
|
||||
if (res != null)
|
||||
MessageBox.Show(res);
|
||||
LoadChatPage();
|
||||
}
|
||||
}
|
||||
}
|
||||
+1882
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,121 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
using TGS.Interface;
|
||||
using TGS.Interface.Components;
|
||||
|
||||
namespace TGS.ControlPanel
|
||||
{
|
||||
/// <summary>
|
||||
/// The main <see cref="ControlPanel"/> form
|
||||
/// </summary>
|
||||
sealed partial class ControlPanel : CountedForm
|
||||
{
|
||||
/// <summary>
|
||||
/// List of instances being used by open control panels
|
||||
/// </summary>
|
||||
public static IDictionary<string, ControlPanel> InstancesInUse { get; private set; } = new Dictionary<string, ControlPanel>();
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IServerInterface"/> instance for this <see cref="ControlPanel"/>
|
||||
/// </summary>
|
||||
readonly IServerInterface Interface;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a <see cref="ControlPanel"/>
|
||||
/// </summary>
|
||||
/// <param name="I">The <see cref="IServerInterface"/> for the <see cref="ControlPanel"/></param>
|
||||
public ControlPanel(IServerInterface I)
|
||||
{
|
||||
InitializeComponent();
|
||||
FormClosed += ControlPanel_FormClosed;
|
||||
Interface = I;
|
||||
if (Interface.IsRemoteConnection)
|
||||
{
|
||||
var splits = Interface.GetServiceComponent<ITGLanding>().Version().Split(' ');
|
||||
Text = String.Format("TGS {0}: {1}:{2}", splits[splits.Length - 1], Interface.HTTPSURL, Interface.HTTPSPort);
|
||||
}
|
||||
Text += " Instance: " + I.InstanceName;
|
||||
if (Interface.VersionMismatch(out string error) && MessageBox.Show(error, "Warning", MessageBoxButtons.OKCancel) == DialogResult.Cancel)
|
||||
{
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
Panels.SelectedIndexChanged += Panels_SelectedIndexChanged;
|
||||
Panels.SelectedIndex += Math.Min(Properties.Settings.Default.LastPageIndex, Panels.TabCount - 1);
|
||||
InitRepoPage();
|
||||
InitBYONDPage();
|
||||
InitServerPage();
|
||||
UpdateSelectedPanel();
|
||||
InstancesInUse.Add(I.InstanceName, this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the <see cref="ControlPanel"/> is closed
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender of the event</param>
|
||||
/// <param name="e">The <see cref="EventArgs"/></param>
|
||||
void ControlPanel_FormClosed(object sender, FormClosedEventArgs e)
|
||||
{
|
||||
InstancesInUse.Remove(Interface.InstanceName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called from <see cref="Dispose(bool)"/>
|
||||
/// </summary>
|
||||
void Cleanup()
|
||||
{
|
||||
InstancesInUse.Remove(Interface.InstanceName);
|
||||
Interface.Dispose();
|
||||
}
|
||||
|
||||
private void Main_Resize(object sender, EventArgs e)
|
||||
{
|
||||
Panels.Location = new Point(10, 10);
|
||||
Panels.Width = ClientSize.Width - 20;
|
||||
Panels.Height = ClientSize.Height - 20;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the content of <see cref="TabControl.SelectedTab"/> of <see cref="Panels"/>
|
||||
/// </summary>
|
||||
void UpdateSelectedPanel()
|
||||
{
|
||||
switch (Panels.SelectedIndex)
|
||||
{
|
||||
case 0: //repo
|
||||
PopulateRepoFields();
|
||||
break;
|
||||
case 1: //byond
|
||||
UpdateBYONDButtons();
|
||||
break;
|
||||
case 2: //scp
|
||||
LoadServerPage();
|
||||
break;
|
||||
case 3: //chat
|
||||
LoadChatPage();
|
||||
break;
|
||||
case 4: //static
|
||||
InitStaticPage();
|
||||
break;
|
||||
}
|
||||
Properties.Settings.Default.LastPageIndex = Panels.SelectedIndex;
|
||||
}
|
||||
|
||||
void Panels_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
UpdateSelectedPanel();
|
||||
}
|
||||
|
||||
bool CheckAdminWithWarning()
|
||||
{
|
||||
if (!Interface.ConnectToInstance().HasFlag(ConnectivityLevel.Administrator))
|
||||
{
|
||||
MessageBox.Show("Only system administrators may use this command!");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,352 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Forms;
|
||||
using System.Threading;
|
||||
using TGS.Interface;
|
||||
using TGS.Interface.Components;
|
||||
|
||||
namespace TGS.ControlPanel
|
||||
{
|
||||
partial class ControlPanel
|
||||
{
|
||||
enum RepoAction {
|
||||
Clone,
|
||||
Checkout,
|
||||
Update,
|
||||
Merge,
|
||||
Reset,
|
||||
Test,
|
||||
Wait,
|
||||
GenCL,
|
||||
}
|
||||
|
||||
RepoAction action;
|
||||
string CloneRepoURL;
|
||||
string CheckoutBranch;
|
||||
int TestPR;
|
||||
|
||||
string repoError;
|
||||
|
||||
private void InitRepoPage()
|
||||
{
|
||||
RepoBGW.ProgressChanged += RepoBGW_ProgressChanged;
|
||||
RepoBGW.RunWorkerCompleted += RepoBGW_RunWorkerCompleted;
|
||||
RepoBGW.DoWork += RepoBGW_DoWork;
|
||||
BackupTagsList.MouseDoubleClick += BackupTagsList_MouseDoubleClick;
|
||||
}
|
||||
|
||||
private void BackupTagsList_MouseDoubleClick(object sender, MouseEventArgs e)
|
||||
{
|
||||
int index = BackupTagsList.IndexFromPoint(e.Location);
|
||||
if (index != ListBox.NoMatches)
|
||||
{
|
||||
var indexText = (string)BackupTagsList.Items[index];
|
||||
if (indexText == "None" || indexText == "Unknown")
|
||||
return;
|
||||
var tagname = indexText.Split(':')[0];
|
||||
var spaceSplits = indexText.Split(' ');
|
||||
var sha = spaceSplits[spaceSplits.Length - 1];
|
||||
|
||||
if (MessageBox.Show(String.Format("Checkout tag {0} ({1})?", tagname, sha), "Restore Backup", MessageBoxButtons.YesNo) != DialogResult.Yes)
|
||||
return;
|
||||
|
||||
CheckoutBranch = tagname;
|
||||
DoAsyncOp(RepoAction.Checkout, "Checking out " + tagname + "...");
|
||||
}
|
||||
}
|
||||
|
||||
private void RepoBGW_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
|
||||
{
|
||||
RepoProgressBar.Value = 100;
|
||||
RepoProgressBar.Style = ProgressBarStyle.Blocks;
|
||||
RepoPanel.UseWaitCursor = false;
|
||||
PopulateRepoFields();
|
||||
}
|
||||
|
||||
private void RepoRefreshButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
PopulateRepoFields();
|
||||
}
|
||||
|
||||
private void PopulateRepoFields()
|
||||
{
|
||||
if (repoError != null)
|
||||
MessageBox.Show("An error occured: " + repoError);
|
||||
|
||||
if (RepoBusyCheck())
|
||||
return;
|
||||
|
||||
var Repo = Interface.GetComponent<ITGRepository>();
|
||||
|
||||
RepoProgressBar.Style = ProgressBarStyle.Marquee;
|
||||
RepoProgressBar.Visible = false;
|
||||
RemoteNameTitle.Visible = true;
|
||||
RepoRemoteTextBox.Visible = true;
|
||||
BranchNameTitle.Visible = true;
|
||||
RepoBranchTextBox.Visible = true;
|
||||
RepoRefreshButton.Visible = true;
|
||||
SyncCommitsCheckBox.Visible = true;
|
||||
SyncCommitsCheckBox.Checked = Repo.PushTestmergeCommits();
|
||||
|
||||
if (!Repo.Exists())
|
||||
{
|
||||
//repo unavailable
|
||||
RepoRemoteTextBox.Text = "https://github.com/tgstation/tgstation";
|
||||
RepoBranchTextBox.Text = "master";
|
||||
RepoProgressBarLabel.Text = "Unable to locate repository";
|
||||
CloneRepositoryButton.Visible = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
RepoProgressBarLabel.Visible = false;
|
||||
|
||||
CurrentRevisionLabel.Visible = true;
|
||||
CurrentRevisionTitle.Visible = true;
|
||||
IdentityLabel.Visible = true;
|
||||
MergePRButton.Visible = true;
|
||||
TestMergeListLabel.Visible = true;
|
||||
TestMergeListTitle.Visible = true;
|
||||
UpdateRepoButton.Visible = true;
|
||||
BackupTagsList.Visible = true;
|
||||
HardReset.Visible = true;
|
||||
RepoApplyButton.Visible = true;
|
||||
TestmergeSelector.Visible = true;
|
||||
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";
|
||||
RepoBranchTextBox.Text = Repo.GetBranch(out error) ?? "Unknown";
|
||||
|
||||
var Backups = Repo.ListBackups(out error);
|
||||
BackupTagsList.Items.Clear();
|
||||
if (Backups != null)
|
||||
{
|
||||
if (Backups.Count == 0)
|
||||
BackupTagsList.Items.Add("None");
|
||||
else
|
||||
foreach (var I in Backups)
|
||||
BackupTagsList.Items.Add(I.Key + ": " + I.Value);
|
||||
}
|
||||
else
|
||||
BackupTagsList.Items.Add("Unknown");
|
||||
|
||||
var PRs = Repo.MergedPullRequests(out error);
|
||||
TestMergeListLabel.Items.Clear();
|
||||
if (PRs != null)
|
||||
if (PRs.Count == 0)
|
||||
TestMergeListLabel.Items.Add("None");
|
||||
else
|
||||
foreach (var I in PRs)
|
||||
TestMergeListLabel.Items.Add(String.Format("#{0}: {2} by {3} at commit {1}\r\n", I.Number, I.Sha, I.Title, I.Author));
|
||||
else
|
||||
TestMergeListLabel.Items.Add("Unknown");
|
||||
}
|
||||
}
|
||||
|
||||
bool RepoBusyCheck()
|
||||
{
|
||||
if (Interface.GetComponent<ITGRepository>().OperationInProgress())
|
||||
{
|
||||
DoAsyncOp(RepoAction.Wait, "Waiting for repository to finish another action...");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private void RepoBGW_ProgressChanged(object sender, ProgressChangedEventArgs e)
|
||||
{
|
||||
var val = e.ProgressPercentage;
|
||||
if (val < 0)
|
||||
{
|
||||
RepoProgressBar.Style = ProgressBarStyle.Marquee;
|
||||
return;
|
||||
}
|
||||
RepoProgressBar.Style = ProgressBarStyle.Blocks;
|
||||
RepoProgressBar.Value = val;
|
||||
}
|
||||
|
||||
private void RepoBGW_DoWork(object sender, DoWorkEventArgs e)
|
||||
{
|
||||
//Only for clones
|
||||
var Repo = Interface.GetComponent<ITGRepository>();
|
||||
|
||||
switch (action) {
|
||||
case RepoAction.Clone:
|
||||
repoError = Repo.Setup(CloneRepoURL, CheckoutBranch);
|
||||
break;
|
||||
case RepoAction.Checkout:
|
||||
repoError = Repo.Checkout(CheckoutBranch);
|
||||
break;
|
||||
case RepoAction.Merge:
|
||||
repoError = Repo.Update(false);
|
||||
break;
|
||||
case RepoAction.Reset:
|
||||
repoError = Repo.Reset(true);
|
||||
break;
|
||||
case RepoAction.Test:
|
||||
repoError = Repo.MergePullRequest(TestPR);
|
||||
break;
|
||||
case RepoAction.Update:
|
||||
repoError = Repo.Update(true);
|
||||
break;
|
||||
case RepoAction.Wait:
|
||||
break;
|
||||
case RepoAction.GenCL:
|
||||
var result = Repo.GenerateChangelog(out repoError);
|
||||
if(repoError != null)
|
||||
repoError += ": " + result;
|
||||
break;
|
||||
default:
|
||||
//reeee
|
||||
return;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
RepoBGW.ReportProgress(Repo.CheckoutProgress());
|
||||
} while (Repo.OperationInProgress());
|
||||
}
|
||||
|
||||
private void CloneRepositoryButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
CloneRepo();
|
||||
}
|
||||
|
||||
void CloneRepo()
|
||||
{
|
||||
CloneRepoURL = RepoRemoteTextBox.Text;
|
||||
CheckoutBranch = RepoBranchTextBox.Text;
|
||||
|
||||
DoAsyncOp(RepoAction.Clone, String.Format("Cloning {0} branch of {1}...", CheckoutBranch, CloneRepoURL));
|
||||
}
|
||||
private void RecloneButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
var DialogResult = MessageBox.Show("This will re-clone the repository, backup, and reset the Static configuration folders. Continue?", "Confim", MessageBoxButtons.YesNo);
|
||||
if (DialogResult == DialogResult.No)
|
||||
return;
|
||||
CloneRepo();
|
||||
}
|
||||
void DoAsyncOp(RepoAction ra, string message)
|
||||
{
|
||||
if (RepoBGW.IsBusy || (ra != RepoAction.Wait && RepoBusyCheck()))
|
||||
return;
|
||||
|
||||
SyncCommitsCheckBox.Visible = false;
|
||||
CurrentRevisionLabel.Visible = false;
|
||||
CurrentRevisionTitle.Visible = false;
|
||||
TestMergeListLabel.Visible = false;
|
||||
TestMergeListTitle.Visible = false;
|
||||
RepoApplyButton.Visible = false;
|
||||
UpdateRepoButton.Visible = false;
|
||||
MergePRButton.Visible = false;
|
||||
CloneRepositoryButton.Visible = false;
|
||||
RemoteNameTitle.Visible = false;
|
||||
RepoRemoteTextBox.Visible = false;
|
||||
BranchNameTitle.Visible = false;
|
||||
RepoBranchTextBox.Visible = false;
|
||||
RepoProgressBar.Visible = true;
|
||||
HardReset.Visible = false;
|
||||
IdentityLabel.Visible = false;
|
||||
TestmergeSelector.Visible = false;
|
||||
RepoGenChangelogButton.Visible = false;
|
||||
RecloneButton.Visible = false;
|
||||
ResetRemote.Visible = false;
|
||||
BackupTagsList.Visible = false;
|
||||
RepoRefreshButton.Visible = false;
|
||||
TGSJsonUpdate.Visible = false;
|
||||
|
||||
RepoPanel.UseWaitCursor = true;
|
||||
|
||||
RepoProgressBar.Value = 0;
|
||||
RepoProgressBar.Style = ProgressBarStyle.Marquee;
|
||||
|
||||
RepoProgressBarLabel.Text = message;
|
||||
RepoProgressBarLabel.Visible = true;
|
||||
|
||||
action = ra;
|
||||
repoError = null;
|
||||
|
||||
RepoBGW.RunWorkerAsync();
|
||||
}
|
||||
private void RepoApplyButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
var Repo = Interface.GetComponent<ITGRepository>();
|
||||
|
||||
if (RepoBusyCheck())
|
||||
return;
|
||||
|
||||
var remote = Repo.GetRemote(out string error);
|
||||
if (remote == null) {
|
||||
MessageBox.Show("Error: " + error);
|
||||
return;
|
||||
}
|
||||
|
||||
var Reclone = remote != RepoRemoteTextBox.Text;
|
||||
if (Reclone)
|
||||
{
|
||||
var DialogResult = MessageBox.Show("Changing the remote URL requires a re-cloning of the repository. Continue?", "Confim", MessageBoxButtons.YesNo);
|
||||
if (DialogResult == DialogResult.No)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Reclone)
|
||||
{
|
||||
Repo.SetPushTestmergeCommits(SyncCommitsCheckBox.Checked);
|
||||
var branch = Repo.GetBranch(out error);
|
||||
if(branch == null)
|
||||
{
|
||||
MessageBox.Show("Error: " + error);
|
||||
return;
|
||||
}
|
||||
|
||||
CheckoutBranch = RepoBranchTextBox.Text;
|
||||
if(branch != CheckoutBranch)
|
||||
DoAsyncOp(RepoAction.Checkout, String.Format("Checking out {0}...", CheckoutBranch));
|
||||
}
|
||||
else
|
||||
CloneRepositoryButton_Click(null, null);
|
||||
}
|
||||
private void UpdateRepoButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
DoAsyncOp(RepoAction.Merge, "Merging origin branch...");
|
||||
}
|
||||
|
||||
private void HardReset_Click(object sender, EventArgs e)
|
||||
{
|
||||
DoAsyncOp(RepoAction.Reset, "Resetting to origin branch...");
|
||||
}
|
||||
|
||||
private void ResetRemote_Click(object sender, EventArgs e)
|
||||
{
|
||||
DoAsyncOp(RepoAction.Update, "Updating and resetting to remote branch...");
|
||||
}
|
||||
|
||||
private void TestMergeButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (TestmergeSelector.Value == 0)
|
||||
{
|
||||
MessageBox.Show("Invalid PR number!");
|
||||
return;
|
||||
}
|
||||
TestPR = (int)TestmergeSelector.Value;
|
||||
DoAsyncOp(RepoAction.Test, String.Format("Merging latest commit of PR #{0}...", TestPR));
|
||||
}
|
||||
|
||||
private void RepoGenChangelogButton_Click(object sender, System.EventArgs e)
|
||||
{
|
||||
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 = Interface.GetComponent<ITGRepository>().UpdateTGS3Json();
|
||||
if (res != null)
|
||||
MessageBox.Show(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,510 @@
|
||||
using Octokit;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using TGS.Interface;
|
||||
using TGS.Interface.Components;
|
||||
|
||||
namespace TGS.ControlPanel
|
||||
{
|
||||
partial class ControlPanel
|
||||
{
|
||||
bool updatingFields = false;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="GitHubClient"/> used for checking the merged state of <see cref="PullRequest"/>s
|
||||
/// </summary>
|
||||
GitHubClient ghclient;
|
||||
|
||||
void InitServerPage()
|
||||
{
|
||||
projectNameText.LostFocus += ProjectNameText_LostFocus;
|
||||
projectNameText.KeyDown += ProjectNameText_KeyDown;
|
||||
ServerStartBGW.RunWorkerCompleted += ServerStartBGW_RunWorkerCompleted;
|
||||
ghclient = new GitHubClient(new ProductHeaderValue(Assembly.GetExecutingAssembly().GetName().Name));
|
||||
var config = Properties.Settings.Default;
|
||||
if (!String.IsNullOrWhiteSpace(config.GitHubAPIKey))
|
||||
ghclient.Credentials = new Credentials(Helpers.DecryptData(config.GitHubAPIKey, config.GitHubAPIKeyEntropy));
|
||||
}
|
||||
|
||||
private void ServerStartBGW_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
|
||||
{
|
||||
if (e.Result != null)
|
||||
MessageBox.Show((string)e.Result);
|
||||
LoadServerPage();
|
||||
}
|
||||
|
||||
private void ProjectNameText_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.KeyCode == Keys.Enter)
|
||||
UpdateProjectName();
|
||||
}
|
||||
|
||||
private void CompileCancelButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
var res = Interface.GetComponent<ITGCompiler>().Cancel();
|
||||
if (res != null)
|
||||
MessageBox.Show(res);
|
||||
LoadServerPage();
|
||||
}
|
||||
|
||||
void LoadServerPage()
|
||||
{
|
||||
var RepoExists = Interface.GetComponent<ITGRepository>().Exists();
|
||||
compileButton.Visible = RepoExists;
|
||||
AutoUpdateCheckbox.Visible = RepoExists;
|
||||
initializeButton.Visible = RepoExists;
|
||||
AutostartCheckbox.Visible = RepoExists;
|
||||
WebclientCheckBox.Visible = RepoExists;
|
||||
PortSelector.Visible = RepoExists;
|
||||
projectNameText.Visible = RepoExists;
|
||||
CompilerStatusLabel.Visible = RepoExists;
|
||||
CompileCancelButton.Visible = RepoExists;
|
||||
CompilerLabel.Visible = RepoExists;
|
||||
ProjectPathLabel.Visible = RepoExists;
|
||||
ServerGStopButton.Visible = RepoExists;
|
||||
ServerStartButton.Visible = RepoExists;
|
||||
ServerGRestartButton.Visible = RepoExists;
|
||||
ServerRestartButton.Visible = RepoExists;
|
||||
PortLabel.Visible = RepoExists;
|
||||
ServerStopButton.Visible = RepoExists;
|
||||
TestMergeManagerButton.Visible = RepoExists;
|
||||
UpdateServerButton.Visible = RepoExists;
|
||||
RemoveAllTestMergesButton.Visible = RepoExists;
|
||||
WorldAnnounceField.Visible = RepoExists;
|
||||
WorldAnnounceButton.Visible = RepoExists;
|
||||
WorldAnnounceLabel.Visible = RepoExists;
|
||||
SyncCommitsCheckBox.Visible = RepoExists;
|
||||
|
||||
if (updatingFields)
|
||||
return;
|
||||
|
||||
var DM = Interface.GetComponent<ITGCompiler>();
|
||||
var DD = Interface.GetComponent<ITGDreamDaemon>();
|
||||
var Config = Interface.GetComponent<ITGConfig>();
|
||||
var Repo = Interface.GetComponent<ITGRepository>();
|
||||
|
||||
try
|
||||
{
|
||||
updatingFields = true;
|
||||
|
||||
ServerPathLabel.Text = "Server Path: " + Interface.GetComponent<ITGInstance>().ServerDirectory();
|
||||
|
||||
SecuritySelector.SelectedIndex = (int)DD.SecurityLevel();
|
||||
|
||||
if (!RepoExists)
|
||||
return;
|
||||
|
||||
var interval = Repo.AutoUpdateInterval();
|
||||
var interval_not_zero = interval != 0;
|
||||
AutoUpdateCheckbox.Checked = interval_not_zero;
|
||||
AutoUpdateInterval.Visible = interval_not_zero;
|
||||
AutoUpdateMLabel.Visible = interval_not_zero;
|
||||
if (interval_not_zero)
|
||||
AutoUpdateInterval.Value = interval;
|
||||
|
||||
var DaeStat = DD.DaemonStatus();
|
||||
var Online = DaeStat == DreamDaemonStatus.Online;
|
||||
ServerStartButton.Enabled = !Online;
|
||||
ServerGStopButton.Enabled = Online;
|
||||
ServerGRestartButton.Enabled = Online;
|
||||
ServerStopButton.Enabled = Online;
|
||||
ServerRestartButton.Enabled = Online;
|
||||
|
||||
switch (DaeStat)
|
||||
{
|
||||
case DreamDaemonStatus.HardRebooting:
|
||||
ServerStatusLabel.Text = "REBOOTING";
|
||||
break;
|
||||
case DreamDaemonStatus.Offline:
|
||||
ServerStatusLabel.Text = "OFFLINE";
|
||||
break;
|
||||
case DreamDaemonStatus.Online:
|
||||
ServerStatusLabel.Text = "ONLINE";
|
||||
var pc = DD.PlayerCount();
|
||||
if (pc != -1)
|
||||
ServerStatusLabel.Text += " (" + pc + " players)";
|
||||
break;
|
||||
}
|
||||
|
||||
ServerGStopButton.Checked = DD.ShutdownInProgress();
|
||||
|
||||
AutostartCheckbox.Checked = DD.Autostart();
|
||||
WebclientCheckBox.Checked = DD.Webclient();
|
||||
if (!PortSelector.Focused)
|
||||
PortSelector.Value = DD.Port();
|
||||
if (!projectNameText.Focused)
|
||||
projectNameText.Text = DM.ProjectName();
|
||||
|
||||
UpdateServerButton.Enabled = false;
|
||||
TestMergeManagerButton.Enabled = false;
|
||||
RemoveAllTestMergesButton.Enabled = false;
|
||||
switch (DM.GetStatus())
|
||||
{
|
||||
case CompilerStatus.Compiling:
|
||||
CompilerStatusLabel.Text = "Compiling...";
|
||||
compileButton.Enabled = false;
|
||||
initializeButton.Enabled = false;
|
||||
CompileCancelButton.Enabled = true;
|
||||
break;
|
||||
case CompilerStatus.Initializing:
|
||||
CompilerStatusLabel.Text = "Initializing...";
|
||||
compileButton.Enabled = false;
|
||||
initializeButton.Enabled = false;
|
||||
CompileCancelButton.Enabled = false;
|
||||
break;
|
||||
case CompilerStatus.Initialized:
|
||||
CompilerStatusLabel.Text = "Idle";
|
||||
initializeButton.Enabled = true;
|
||||
compileButton.Enabled = true;
|
||||
CompileCancelButton.Enabled = false;
|
||||
UpdateServerButton.Enabled = true;
|
||||
TestMergeManagerButton.Enabled = true;
|
||||
RemoveAllTestMergesButton.Enabled = true;
|
||||
break;
|
||||
case CompilerStatus.Uninitialized:
|
||||
CompilerStatusLabel.Text = "Uninitialized";
|
||||
compileButton.Enabled = false;
|
||||
initializeButton.Enabled = true;
|
||||
CompileCancelButton.Enabled = false;
|
||||
break;
|
||||
default:
|
||||
CompilerStatusLabel.Text = "Unknown!";
|
||||
initializeButton.Enabled = true;
|
||||
compileButton.Enabled = true;
|
||||
CompileCancelButton.Enabled = true;
|
||||
break;
|
||||
}
|
||||
var error = DM.CompileError();
|
||||
if (error != null)
|
||||
MessageBox.Show("Error: " + error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
updatingFields = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void ProjectNameText_LostFocus(object sender, EventArgs e)
|
||||
{
|
||||
UpdateProjectName();
|
||||
}
|
||||
|
||||
void UpdateProjectName()
|
||||
{
|
||||
if (!updatingFields)
|
||||
Interface.GetComponent<ITGCompiler>().SetProjectName(projectNameText.Text);
|
||||
}
|
||||
|
||||
private void PortSelector_ValueChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (!updatingFields)
|
||||
Interface.GetComponent<ITGDreamDaemon>().SetPort((ushort)PortSelector.Value);
|
||||
}
|
||||
|
||||
private void ServerPageRefreshButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
LoadServerPage();
|
||||
}
|
||||
|
||||
private void InitializeButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (!Interface.GetComponent<ITGCompiler>().Initialize())
|
||||
MessageBox.Show("Unable to start initialization!");
|
||||
LoadServerPage();
|
||||
}
|
||||
private void CompileButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (!Interface.GetComponent<ITGCompiler>().Compile())
|
||||
MessageBox.Show("Unable to start compilation!");
|
||||
LoadServerPage();
|
||||
}
|
||||
|
||||
private void AutostartCheckbox_CheckedChanged(object sender, System.EventArgs e)
|
||||
{
|
||||
if (!updatingFields)
|
||||
Interface.GetComponent<ITGDreamDaemon>().SetAutostart(AutostartCheckbox.Checked);
|
||||
}
|
||||
private void ServerStartButton_Click(object sender, System.EventArgs e)
|
||||
{
|
||||
if (!ServerStartBGW.IsBusy)
|
||||
ServerStartBGW.RunWorkerAsync();
|
||||
}
|
||||
|
||||
private void ServerStartBGW_DoWork(object sender, DoWorkEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
e.Result = Interface.GetComponent<ITGDreamDaemon>().Start();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
e.Result = ex.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
private void ServerStopButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
var DialogResult = MessageBox.Show("This will immediately shut down the server. Continue?", "Confim", MessageBoxButtons.YesNo);
|
||||
if (DialogResult == DialogResult.No)
|
||||
return;
|
||||
var res = Interface.GetComponent<ITGDreamDaemon>().Stop();
|
||||
if (res != null)
|
||||
MessageBox.Show(res);
|
||||
}
|
||||
|
||||
private void ServerRestartButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
var DialogResult = MessageBox.Show("This will immediately restart the server. Continue?", "Confim", MessageBoxButtons.YesNo);
|
||||
if (DialogResult == DialogResult.No)
|
||||
return;
|
||||
var res = Interface.GetComponent<ITGDreamDaemon>().Restart();
|
||||
if (res != null)
|
||||
MessageBox.Show(res);
|
||||
}
|
||||
|
||||
private void ServerGStopButton_Checked(object sender, EventArgs e)
|
||||
{
|
||||
if (updatingFields)
|
||||
return;
|
||||
var DialogResult = MessageBox.Show("This will shut down the server when the current round ends. Continue?", "Confim", MessageBoxButtons.YesNo);
|
||||
if (DialogResult == DialogResult.No)
|
||||
return;
|
||||
Interface.GetComponent<ITGDreamDaemon>().RequestStop();
|
||||
LoadServerPage();
|
||||
}
|
||||
|
||||
private void ServerGRestartButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
var DialogResult = MessageBox.Show("This will restart the server when the current round ends. Continue?", "Confim", MessageBoxButtons.YesNo);
|
||||
if (DialogResult == DialogResult.No)
|
||||
return;
|
||||
Interface.GetComponent<ITGDreamDaemon>().RequestRestart();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Launches the <see cref="TestMergeManager"/>
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender of the event</param>
|
||||
/// <param name="e">The <see cref="EventArgs"/></param>
|
||||
void TestMergeManagerButton_Click(object sender, System.EventArgs e)
|
||||
{
|
||||
using (var TMM = new TestMergeManager(Interface, ghclient))
|
||||
TMM.ShowDialog();
|
||||
LoadServerPage();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calls <see cref="UpdateServer"/>
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender of the event</param>
|
||||
/// <param name="e">The <see cref="EventArgs"/></param>
|
||||
void UpdateServerButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
UpdateServer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calls <see cref="ITGRepository.Update(bool)"/> with a <see langword="true"/> parameter, re-merging any current <see cref="PullRequest"/>s at their current commit, calls <see cref="ITGRepository.GenerateChangelog(out string)"/> and <see cref="ITGRepository.SynchronizePush"/>, and starts the <see cref="ITGCompiler.Compile(bool)"/> prompting the user with any errors that may occur. Merged <see cref="PullRequest"/>s are not remerged
|
||||
/// </summary>
|
||||
async void UpdateServer()
|
||||
{
|
||||
try
|
||||
{
|
||||
UseWaitCursor = true;
|
||||
Enabled = false;
|
||||
try
|
||||
{
|
||||
string res = null;
|
||||
var repo = Interface.GetComponent<ITGRepository>();
|
||||
var pulls = await Task.Factory.StartNew(() => repo.MergedPullRequests(out res));
|
||||
|
||||
if (pulls == null)
|
||||
{
|
||||
MessageBox.Show(res);
|
||||
return;
|
||||
}
|
||||
|
||||
List<Task<PullRequest>> pullsRequests = null;
|
||||
if(Program.GetRepositoryRemote(repo, out string remoteOwner, out string remoteName)) {
|
||||
//find out which of the PRs have been merged
|
||||
pullsRequests = new List<Task<PullRequest>>();
|
||||
foreach (var I in pulls)
|
||||
pullsRequests.Add(ghclient.PullRequest.Get(remoteOwner, remoteName, I.Number));
|
||||
}
|
||||
|
||||
res = await Task.Factory.StartNew(() => repo.Update(true));
|
||||
|
||||
if(res != null)
|
||||
{
|
||||
MessageBox.Show(res, "Error updating repository");
|
||||
return;
|
||||
}
|
||||
|
||||
await Task.Factory.StartNew(() => repo.GenerateChangelog(out res));
|
||||
|
||||
if (res != null)
|
||||
{
|
||||
MessageBox.Show(res, "Error generating changelog");
|
||||
return;
|
||||
}
|
||||
|
||||
res = await Task.Factory.StartNew(() => repo.SynchronizePush());
|
||||
|
||||
if (res != null)
|
||||
{
|
||||
MessageBox.Show(res, "Error synchronizing commits");
|
||||
return;
|
||||
}
|
||||
|
||||
if (pullsRequests != null)
|
||||
Task.WaitAll(pullsRequests.ToArray());
|
||||
|
||||
foreach (var I in pullsRequests)
|
||||
if (I.Result.Merged)
|
||||
pulls.RemoveAll(x => x.Number == I.Result.Number);
|
||||
|
||||
var results = new List<string>();
|
||||
foreach (var I in pulls) {
|
||||
retry:
|
||||
await Task.Factory.StartNew(() => res = repo.MergePullRequest(I.Number, I.Sha));
|
||||
if (res != null)
|
||||
switch(MessageBox.Show(res, "Error Re-merging Pull Request", MessageBoxButtons.AbortRetryIgnore))
|
||||
{
|
||||
case DialogResult.Abort:
|
||||
return;
|
||||
case DialogResult.Retry:
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
await Task.Factory.StartNew(() => Interface.GetComponent<ITGCompiler>().Compile(pulls.Count != 1));
|
||||
if (res != null)
|
||||
MessageBox.Show(res, "Error starting compile!");
|
||||
}
|
||||
finally
|
||||
{
|
||||
UseWaitCursor = false;
|
||||
Enabled = true;
|
||||
}
|
||||
}
|
||||
catch (ForbiddenException)
|
||||
{
|
||||
if (ghclient.Credentials.AuthenticationType == AuthenticationType.Anonymous)
|
||||
{
|
||||
if (Program.RateLimitPrompt(ghclient))
|
||||
UpdateServer();
|
||||
return;
|
||||
}
|
||||
else
|
||||
throw;
|
||||
}
|
||||
LoadServerPage();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calls <see cref="ITGRepository.Reset(bool)"/> with a <see langword="true"/> parameter, calls <see cref="ITGRepository.GenerateChangelog(out string)"/>, and starts the <see cref="ITGCompiler.Compile(bool)"/> prompting the user with any errors that may occur.
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender of the event</param>
|
||||
/// <param name="e">The <see cref="EventArgs"/></param>
|
||||
async void RemoveAllTestMergesButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
UseWaitCursor = true;
|
||||
Enabled = false;
|
||||
try
|
||||
{
|
||||
var repo = Interface.GetComponent<ITGRepository>();
|
||||
|
||||
var res = await Task.Factory.StartNew(() => repo.Reset(true));
|
||||
|
||||
if (res != null)
|
||||
{
|
||||
MessageBox.Show(res, "Error resetting repository");
|
||||
return;
|
||||
}
|
||||
|
||||
await Task.Factory.StartNew(() => repo.GenerateChangelog(out res));
|
||||
|
||||
if (res != null)
|
||||
{
|
||||
MessageBox.Show(res, "Error generating changelog");
|
||||
return;
|
||||
}
|
||||
|
||||
await Task.Factory.StartNew(() => Interface.GetComponent<ITGCompiler>().Compile(false));
|
||||
if (res != null)
|
||||
MessageBox.Show(res, "Error starting compile!");
|
||||
}
|
||||
finally
|
||||
{
|
||||
UseWaitCursor = false;
|
||||
Enabled = true;
|
||||
}
|
||||
}
|
||||
catch (ForbiddenException)
|
||||
{
|
||||
if (ghclient.Credentials.AuthenticationType == AuthenticationType.Anonymous)
|
||||
{
|
||||
if (Program.RateLimitPrompt(ghclient))
|
||||
UpdateServer();
|
||||
return;
|
||||
}
|
||||
else
|
||||
throw;
|
||||
}
|
||||
LoadServerPage();
|
||||
}
|
||||
|
||||
private void SecuritySelector_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (!updatingFields)
|
||||
if (!Interface.GetComponent<ITGDreamDaemon>().SetSecurityLevel((DreamDaemonSecurity)SecuritySelector.SelectedIndex))
|
||||
MessageBox.Show("Security change will be applied after next server reboot.");
|
||||
}
|
||||
|
||||
private void WorldAnnounceButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
var msg = WorldAnnounceField.Text;
|
||||
if (!String.IsNullOrWhiteSpace(msg))
|
||||
{
|
||||
var res = Interface.GetComponent<ITGDreamDaemon>().WorldAnnounce(msg);
|
||||
if (res != null)
|
||||
{
|
||||
MessageBox.Show(res);
|
||||
return;
|
||||
}
|
||||
}
|
||||
WorldAnnounceField.Text = "";
|
||||
}
|
||||
|
||||
private void WebclientCheckBox_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (!updatingFields)
|
||||
Interface.GetComponent<ITGDreamDaemon>().SetWebclient(WebclientCheckBox.Checked);
|
||||
}
|
||||
|
||||
private void AutoUpdateInterval_ValueChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (!updatingFields)
|
||||
Interface.GetComponent<ITGRepository>().SetAutoUpdateInterval((ulong)AutoUpdateInterval.Value);
|
||||
}
|
||||
|
||||
private void AutoUpdateCheckbox_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (updatingFields)
|
||||
return;
|
||||
var on = AutoUpdateCheckbox.Visible && AutoUpdateCheckbox.Checked;
|
||||
AutoUpdateInterval.Visible = on;
|
||||
AutoUpdateMLabel.Visible = on;
|
||||
if (!on)
|
||||
Interface.GetComponent<ITGRepository>().SetAutoUpdateInterval(0);
|
||||
else
|
||||
Interface.GetComponent<ITGRepository>().SetAutoUpdateInterval((ulong)AutoUpdateInterval.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,353 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
using TGS.Interface;
|
||||
using TGS.Interface.Components;
|
||||
|
||||
namespace TGS.ControlPanel
|
||||
{
|
||||
partial class ControlPanel
|
||||
{
|
||||
IDictionary<int, string> IndexesToPaths = new Dictionary<int, string>();
|
||||
IList<string> EnumeratedPaths = new List<string>() { "" };
|
||||
bool enumerating = false;
|
||||
/// <summary>
|
||||
/// Whether or not the static page has been initialized yet
|
||||
/// </summary>
|
||||
bool initializedStaticPage = false;
|
||||
|
||||
enum EnumResult
|
||||
{
|
||||
Enumerated,
|
||||
Unauthorized,
|
||||
NotEnumerated,
|
||||
Error,
|
||||
}
|
||||
|
||||
void InitStaticPage()
|
||||
{
|
||||
if (initializedStaticPage)
|
||||
return;
|
||||
if(!Interface.ConnectToInstance().HasFlag(ConnectivityLevel.Administrator))
|
||||
RecreateStaticButton.Visible = false;
|
||||
BuildFileList();
|
||||
initializedStaticPage = true;
|
||||
}
|
||||
|
||||
void BuildFileList()
|
||||
{
|
||||
enumerating = true;
|
||||
IndexesToPaths.Clear();
|
||||
StaticFileListBox.Items.Clear();
|
||||
IndexesToPaths.Add(StaticFileListBox.Items.Add("/"), "/");
|
||||
if (EnumeratePath("", Interface.GetComponent<ITGConfig>(), 1) == EnumResult.Unauthorized)
|
||||
{
|
||||
StaticFileListBox.Items[0] += " (UNAUTHORIZED)";
|
||||
IndexesToPaths[0] = null;
|
||||
}
|
||||
StaticFileListBox.SelectedIndex = 0;
|
||||
enumerating = false;
|
||||
}
|
||||
|
||||
EnumResult EnumeratePath(string path, ITGConfig config, int level)
|
||||
{
|
||||
if (!EnumeratedPaths.Contains(path))
|
||||
return EnumResult.NotEnumerated;
|
||||
var Enum = config.ListStaticDirectory(path, out string error, out bool unauthorized);
|
||||
if(Enum == null)
|
||||
{
|
||||
if (unauthorized)
|
||||
return EnumResult.Unauthorized;
|
||||
else
|
||||
{
|
||||
MessageBox.Show(String.Format("Could not enumerate static path \"{0}\" error: {1}", path, error));
|
||||
return EnumResult.Error;
|
||||
}
|
||||
}
|
||||
foreach(var I in Enum)
|
||||
{
|
||||
if(I[0] == '/')
|
||||
{
|
||||
var dir = I.Remove(0, 1);
|
||||
var index = StaticFileListBox.Items.Add(DSNTimes(level) + dir + '/');
|
||||
var fullpath = path + '/' + dir;
|
||||
IndexesToPaths.Add(index, fullpath);
|
||||
switch(EnumeratePath(fullpath, config, level + 1))
|
||||
{
|
||||
case EnumResult.Unauthorized:
|
||||
StaticFileListBox.Items[index] += " (UNAUTHORIZED)";
|
||||
IndexesToPaths[index] = null;
|
||||
break;
|
||||
case EnumResult.NotEnumerated:
|
||||
StaticFileListBox.Items[index] += " (...)";
|
||||
break;
|
||||
case EnumResult.Error:
|
||||
StaticFileListBox.Items[index] += " (ERROR)";
|
||||
IndexesToPaths[index] = null;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
IndexesToPaths.Add(StaticFileListBox.Items.Add(DSNTimes(level) + I), Path.Combine(path, I));
|
||||
}
|
||||
return EnumResult.Enumerated;
|
||||
}
|
||||
|
||||
string DSNTimes(int n)
|
||||
{
|
||||
var res = "";
|
||||
for (var I = 0; I < n; ++I)
|
||||
res += " ";
|
||||
return res;
|
||||
}
|
||||
private void StaticFilesRefreshButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
BuildFileList();
|
||||
UpdateEditText();
|
||||
}
|
||||
|
||||
private void StaticFileUploadButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (StaticFileEditTextbox.Text != "Directory")
|
||||
{
|
||||
MessageBox.Show("Please select a directory to upload the file to.");
|
||||
return;
|
||||
}
|
||||
var ofd = new OpenFileDialog()
|
||||
{
|
||||
CheckFileExists = true,
|
||||
CheckPathExists = true,
|
||||
DefaultExt = ".txt",
|
||||
Multiselect = false,
|
||||
Title = "Static File Upload",
|
||||
ValidateNames = true,
|
||||
Filter = "All files (*.*)|*.*",
|
||||
AddExtension = false,
|
||||
SupportMultiDottedExtensions = true,
|
||||
};
|
||||
if (ofd.ShowDialog() != DialogResult.OK)
|
||||
return;
|
||||
|
||||
var fileToUpload = ofd.FileName;
|
||||
|
||||
var FileName = Path.Combine(IndexesToPaths[StaticFileListBox.SelectedIndex], Path.GetFileName(fileToUpload));
|
||||
|
||||
string fileContents = null;
|
||||
string error = null;
|
||||
try
|
||||
{
|
||||
fileContents = File.ReadAllText(fileToUpload);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
error = ex.ToString();
|
||||
}
|
||||
if (error == null)
|
||||
try
|
||||
{
|
||||
error = Interface.GetComponent<ITGConfig>().WriteText(FileName, fileContents, out bool unauthorized);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
error = "Failed to read file, most likely due to it being too large. The transfer limit is much higher on non-remote connections. " + ex.ToString();
|
||||
}
|
||||
if (error != null)
|
||||
MessageBox.Show("An error occurred: " + error);
|
||||
BuildFileList();
|
||||
}
|
||||
|
||||
private void StaticFileDownloadButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (StaticFileEditTextbox.ReadOnly)
|
||||
{
|
||||
MessageBox.Show("Cannot download this file!");
|
||||
return;
|
||||
}
|
||||
var remotePath = IndexesToPaths[StaticFileListBox.SelectedIndex];
|
||||
if (remotePath == null)
|
||||
return;
|
||||
string text, error;
|
||||
try
|
||||
{
|
||||
text = Interface.GetComponent<ITGConfig>().ReadText(remotePath, false, out error, out bool unauthorized);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
text = null;
|
||||
error = "Failed to read file, most likely due to it being too large. The transfer limit is much higher on non-remote connections. " + ex.ToString();
|
||||
}
|
||||
if (text != null)
|
||||
{
|
||||
var ofd = new SaveFileDialog()
|
||||
{
|
||||
CheckFileExists = false,
|
||||
CheckPathExists = true,
|
||||
DefaultExt = ".txt",
|
||||
Title = "Static File Download",
|
||||
ValidateNames = true,
|
||||
Filter = "All files (*.*)|*.*",
|
||||
AddExtension = false,
|
||||
CreatePrompt = false,
|
||||
OverwritePrompt = true,
|
||||
SupportMultiDottedExtensions = true,
|
||||
};
|
||||
if (ofd.ShowDialog() != DialogResult.OK)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
File.WriteAllText(ofd.FileName, text);
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
error = ex.ToString();
|
||||
}
|
||||
}
|
||||
MessageBox.Show("An error occurred: " + error);
|
||||
}
|
||||
|
||||
private void StaticFileDeleteButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (MessageBox.Show("Are you sure you want to delete " + ((string)StaticFileListBox.SelectedItem).Trim() + "?", "Confirm", MessageBoxButtons.YesNo) != DialogResult.Yes)
|
||||
return;
|
||||
var res = Interface.GetComponent<ITGConfig>().DeleteFile(IndexesToPaths[StaticFileListBox.SelectedIndex], out bool unauthorized);
|
||||
if (res != null)
|
||||
MessageBox.Show(res);
|
||||
BuildFileList();
|
||||
}
|
||||
|
||||
private void StaticFileCreateButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
if(StaticFileEditTextbox.Text != "Directory")
|
||||
{
|
||||
MessageBox.Show("Please select a directory to create the file in.");
|
||||
return;
|
||||
}
|
||||
var FileName = Program.TextPrompt("Static File/Directory Creation", "Enter the name of the file/directory:");
|
||||
if (FileName == null)
|
||||
return;
|
||||
|
||||
var resu = MessageBox.Show("Is this the name of a directory?", "Directory", MessageBoxButtons.YesNoCancel);
|
||||
if (resu == DialogResult.Cancel)
|
||||
return;
|
||||
var FullFileName = Path.Combine(IndexesToPaths[StaticFileListBox.SelectedIndex], FileName);
|
||||
if (resu == DialogResult.Yes)
|
||||
FullFileName = Path.Combine(FullFileName, "__TGS3_CP_DIRECTORY_CREATOR__");
|
||||
var config = Interface.GetComponent<ITGConfig>();
|
||||
var res = config.WriteText(FullFileName, "", out bool unauthorized);
|
||||
if (res != null)
|
||||
MessageBox.Show(res);
|
||||
if (resu == DialogResult.Yes)
|
||||
{
|
||||
FullFileName = Path.Combine(FullFileName, "__TGS3_CP_DIRECTORY_CREATOR__");
|
||||
config.DeleteFile(FullFileName, out unauthorized); //don't care about this
|
||||
}
|
||||
BuildFileList();
|
||||
}
|
||||
|
||||
private void StaticFileSaveButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
var index = StaticFileListBox.SelectedIndex;
|
||||
string res;
|
||||
bool unauthorized;
|
||||
try
|
||||
{
|
||||
res = Interface.GetComponent<ITGConfig>().WriteText(IndexesToPaths[index], StaticFileEditTextbox.Text, out unauthorized);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
unauthorized = false;
|
||||
res = "Failed to write file, most likely due to it being too large. The transfer limit is much higher on non-remote connections. " + ex.ToString();
|
||||
}
|
||||
if (res != null)
|
||||
{
|
||||
MessageBox.Show("Error: " + res);
|
||||
var title = (string)StaticFileListBox.Items[index];
|
||||
if (unauthorized && !title.Contains(" (UNAUTHORIZED)"))
|
||||
StaticFileListBox.Items[index] = title + " (UNAUTHORIZED)";
|
||||
}
|
||||
UpdateEditText();
|
||||
}
|
||||
|
||||
private void StaticFileListBox_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
UpdateEditText();
|
||||
}
|
||||
|
||||
void UpdateEditText()
|
||||
{
|
||||
if (enumerating)
|
||||
return;
|
||||
var newIndex = StaticFileListBox.SelectedIndex;
|
||||
if (newIndex == -1)
|
||||
return;
|
||||
var path = IndexesToPaths[newIndex];
|
||||
var title = (string)StaticFileListBox.Items[newIndex];
|
||||
var authed_title = title.Replace(" (UNAUTHORIZED)", "").Replace(" (...)", "");
|
||||
if (authed_title[authed_title.Length - 1] == '/')
|
||||
{
|
||||
StaticFileEditTextbox.ReadOnly = true;
|
||||
StaticFileEditTextbox.Text = "Directory";
|
||||
if (path != null && path != "/")
|
||||
{
|
||||
EnumeratedPaths.Add(path);
|
||||
BuildFileList();
|
||||
enumerating = true;
|
||||
StaticFileListBox.SelectedIndex = newIndex;
|
||||
enumerating = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string entry, error;
|
||||
bool unauthorized;
|
||||
try
|
||||
{
|
||||
entry = Interface.GetComponent<ITGConfig>().ReadText(path, false, out error, out unauthorized);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
entry = null;
|
||||
unauthorized = false;
|
||||
error = "Failed to read file, most likely due to it being too large. The transfer limit is much higher on non-remote connections. " + e.ToString();
|
||||
}
|
||||
if (entry == null)
|
||||
{
|
||||
StaticFileEditTextbox.ReadOnly = true;
|
||||
StaticFileEditTextbox.Text = "ERROR: " + error;
|
||||
if (unauthorized && !title.Contains(" (UNAUTHORIZED)"))
|
||||
StaticFileListBox.Items[newIndex] = title + " (UNAUTHORIZED)";
|
||||
}
|
||||
else
|
||||
{
|
||||
StaticFileEditTextbox.ReadOnly = false;
|
||||
StaticFileEditTextbox.Text = entry.Replace("\r\n", "\n").Replace("\r", "\n").Replace("\n", Environment.NewLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RecreateStaticButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (!CheckAdminWithWarning())
|
||||
{
|
||||
RecreateStaticButton.Visible = false;
|
||||
return;
|
||||
}
|
||||
if (MessageBox.Show("This will rename the current static directory to a backup and recreate it. Continue?", "Confirm", MessageBoxButtons.YesNo) != DialogResult.Yes)
|
||||
return;
|
||||
if (!CheckAdminWithWarning())
|
||||
{
|
||||
RecreateStaticButton.Visible = false;
|
||||
return;
|
||||
}
|
||||
var res = Interface.GetComponent<ITGAdministration>().RecreateStaticFolder();
|
||||
if (res != null)
|
||||
MessageBox.Show(res);
|
||||
BuildFileList();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user