using Octokit;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows.Forms;
using TGServiceInterface;
using TGServiceInterface.Components;
namespace TGControlPanel
{
sealed partial class TestMergeManager : ServerOpForm
{
///
/// The connected to an to handle the pull requests for
///
readonly IInterface currentInterface;
///
/// Construct a
///
public TestMergeManager(IInterface interfaceToUse)
{
InitializeComponent();
Load += PullRequestManager_Load;
DialogResult = DialogResult.Cancel;
UpdateToRemoteRadioButton.Checked = true;
currentInterface = interfaceToUse;
}
///
/// Populate with from github and check off ones that are currently merged. Prompts the user to login to GitHub if they hit the rate limit
///
/// The to use. If , one will be created
async void LoadPullRequests(GitHubClient client)
{
if(client == null)
client = new GitHubClient(new ProductHeaderValue(Assembly.GetExecutingAssembly().GetName().Name));
var config = Properties.Settings.Default;
if (!String.IsNullOrWhiteSpace(config.GitHubAPIKey))
client.Credentials = new Credentials(Helpers.DecryptData(config.GitHubAPIKey, config.GitHubAPIKeyEntropy));
try
{
Enabled = false;
UseWaitCursor = true;
try
{
PullRequestListBox.Items.Clear();
var repo = currentInterface.GetComponent();
string remote = null, error = null, error2 = null;
IList pulls = null;
var remoteRequest = WrapServerOp(() => remote = repo.GetRemote(out error));
//get started on this while we're processing here
var pullsRequest = Task.Factory.StartNew(() => pulls = repo.MergedPullRequests(out error2));
await remoteRequest;
if (remote == null)
{
MessageBox.Show(String.Format("Error retrieving remote repository: {0}", error));
return;
}
if (!remote.Contains("github.com"))
{
MessageBox.Show("Pull request support is only available for github based repositories!", "Error");
return;
}
//Assume standard gh format: [(git)|(https)]://github.com/owner/repo(.git)[0-1]
var splits = remote.Split('/');
var repoName = splits[splits.Length - 1];
var repoOwner = splits[splits.Length - 2];
//Search for open PRs
Enabled = false;
UseWaitCursor = true;
SearchIssuesResult result;
try
{
result = await client.Search.SearchIssues(new SearchIssuesRequest
{
Repos = new RepositoryCollection { { repoOwner, repoName } },
State = ItemState.Open,
Type = IssueTypeQualifier.PullRequest
});
}
finally
{
Enabled = true;
UseWaitCursor = false;
}
//now we need to know what's merged
await WrapServerOp(() => pullsRequest.Wait());
if (pulls == null)
MessageBox.Show(String.Format("Error retrieving currently merged pull requests: {0}", error2));
foreach (var I in result.Items)
{
bool needsTesting = false;
foreach(var J in I.Labels)
if (J.Name.ToLower().Contains("test"))
{
needsTesting = true;
break;
}
var itemString = String.Format("#{0} - {1}{2}", I.Number, I.Title, needsTesting ? " - TESTING REQUESTED" : "");
var isChecked = pulls.Any(x => x.Number == I.Number);
if (needsTesting || isChecked)
{
PullRequestListBox.Items.Insert(0, itemString);
if(isChecked)
PullRequestListBox.SetItemChecked(0, true);
}
else
PullRequestListBox.Items.Add(itemString, isChecked);
}
}
finally
{
Enabled = true;
UseWaitCursor = false;
}
}
catch (ForbiddenException)
{
if (client.Credentials.AuthenticationType == AuthenticationType.Anonymous) //assume request limit hit
{
if (MessageBox.Show("You seem to have hit the rate limit of 60 requests per hour of the GitHub API for anonymous requests. Would you like to enter credentials to bypass this?", "Rate limited", MessageBoxButtons.YesNo) != DialogResult.Yes)
return;
using (var D = new GitHubLoginPrompt(client))
if (D.ShowDialog() == DialogResult.OK)
LoadPullRequests(client);
}
else
throw;
}
}
///
/// Called when the is loaded
///
/// The sender of the event
/// The
void PullRequestManager_Load(object sender, EventArgs e)
{
LoadPullRequests(null);
}
///
/// Calls and shows the user an error prompt if it fails
///
/// The to call on
async void GenerateChangelog(ITGRepository repo)
{
string error = null;
await WrapServerOp(() => repo.GenerateChangelog(out error));
if (error != null)
MessageBox.Show(String.Format("Error generating changelog: {0}", error));
}
///
/// Called when the is clicked. Calls if necessary, merge pull requests, and call . Closes the if appropriate
///
/// The sender of the event
/// The
async void ApplyButton_Click(object sender, EventArgs e)
{
Enabled = false;
UseWaitCursor = true;
ApplyingPullRequestsLabel.Visible = true;
ApplyingPullRequestsProgressBar.Visible = true;
PullRequestListBox.Visible = false;
try
{
//so first collect a list of pulls that are checked
var pulls = new List();
foreach (var I in PullRequestListBox.CheckedItems)
pulls.Add(Convert.ToInt32(((string)I).Split(' ')[0].Substring(1)));
var repo = currentInterface.GetComponent();
string error = null;
//Do standard repo updates
if (UpdateToRemoteRadioButton.Checked)
await WrapServerOp(() => error = repo.Update(true));
else if (UpdateToOriginRadioButton.Checked)
await WrapServerOp(() => error = repo.Reset(true));
if (error != null)
{
MessageBox.Show(String.Format("Error updating repository: {0}", error));
return;
}
if (UpdateToRemoteRadioButton.Checked)
{
GenerateChangelog(repo);
await WrapServerOp(() => error = repo.SynchronizePush());
if (error != null)
MessageBox.Show(String.Format("Error sychronizing repo: {0}", error));
}
//Merge the PRs, collect errors
IList errors = null;
await WrapServerOp(() =>
{
errors = new List();
foreach (var I in pulls)
{
var res = repo.MergePullRequest(I);
if (res != null)
errors.Add(String.Format("Error merging PR #{0}: {1}", I, res));
}
});
//Show any errors
foreach (var I in errors)
MessageBox.Show(I);
if (errors.Count != 0)
return;
if (pulls.Count > 0)
//regen the changelog
GenerateChangelog(repo);
//Start the compile
if (!currentInterface.GetComponent().Compile(pulls.Count == 1))
MessageBox.Show("Could not start compilation!");
else
MessageBox.Show("Test merges updated and compilation started!");
}
finally
{
Enabled = true;
UseWaitCursor = false;
ApplyingPullRequestsLabel.Visible = false;
ApplyingPullRequestsProgressBar.Visible = false;
PullRequestListBox.Visible = true;
}
}
///
/// Called when the is clicked
///
/// The sender of the event
/// The
void RefreshButton_Click(object sender, EventArgs e)
{
LoadPullRequests(null);
}
}
}