Skip to content

Commit

Permalink
Merge pull request #33 from semdiffdotnet/repo-getpulls
Browse files Browse the repository at this point in the history
Repo and GitHub
  • Loading branch information
shawn-fontaine committed Feb 12, 2016
2 parents 488e158 + 6b670dc commit 8e7c643
Show file tree
Hide file tree
Showing 15 changed files with 348 additions and 143 deletions.
29 changes: 29 additions & 0 deletions SemDiff.Core/Analysis.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using Microsoft.CodeAnalysis.Diagnostics;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace SemDiff.Core
{
Expand All @@ -15,6 +17,7 @@ public class Analysis
/// </summary>
public static IEnumerable<DetectedFalsePositive> ForFalsePositive(Repo repo, SyntaxTree tree, string filePath)
{
var pulls = GetPulls(repo, filePath);
throw new NotImplementedException();
}

Expand All @@ -23,7 +26,33 @@ public static IEnumerable<DetectedFalsePositive> ForFalsePositive(Repo repo, Syn
/// </summary>
public static IEnumerable<DetectedFalseNegative> ForFalseNegative(Repo repo, SemanticModel semanticModel)
{
var baseClassPath = ""; //TODO: find using semantic model
var pulls = GetPulls(repo, baseClassPath);
throw new NotImplementedException();
}

internal static string GetRelativePath(string localDirectory, string filePath)
{
var local = Path.GetFullPath(localDirectory);
var file = Path.GetFullPath(filePath);
if (file.StartsWith(local))
{
return file.Substring(local.Length);
}
else
{
return null;
}
}

internal static IEnumerable<Tuple<RemoteFile, RemoteChanges>> GetPulls(Repo repo, string lookForFile)
{
var relativePath = GetRelativePath(repo.LocalDirectory, lookForFile);
if (string.IsNullOrWhiteSpace(relativePath))
{
return Enumerable.Empty<Tuple<RemoteFile, RemoteChanges>>();
}
return repo.GetRemoteChanges().SelectMany(p => p.Files.Select(f => new { n = f.Filename, f, p })).Where(a => a.n == relativePath).Select(a => Tuple.Create(a.f, a.p)).ToList();
}
}
}
15 changes: 15 additions & 0 deletions SemDiff.Core/Extensions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace SemDiff.Core
{
Expand Down Expand Up @@ -44,5 +45,19 @@ public static Queue<T> GetMergedChangeQueue<T>(this IEnumerable<T> left, IEnumer
}
return result;
}

public async static Task<T> RetryOnce<T>(this Func<Task<T>> tsk, TimeSpan wait)
{
try
{
return await tsk();
}
catch (Exception ex)
{
Logger.Error(ex.Message);
await Task.Delay(wait);
return await tsk();
}
}
}
}
130 changes: 69 additions & 61 deletions SemDiff.Core/GitHub.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using SemDiff.Core.Configuration;
Expand Down Expand Up @@ -26,46 +27,43 @@ public class GitHub

private static string APIDoesNotExistError = "Not Found";

static GitHubConfiguration gitHubConfig =
new GitHubConfiguration((AuthenticationSection)ConfigurationManager.GetSection("SemDiff.Core/authentication"));

public GitHub(string repoOwner, string repoName)
{
this.RepoOwner = repoOwner;
this.RepoName = repoName;

this.RequestsRemaining = 1;
Client = new HttpClient //TODO: Enable gzip!
Client = new HttpClient(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate })
{
BaseAddress = new Uri("https://api.github.com/")
};
Client.DefaultRequestHeaders.UserAgent.ParseAdd(nameof(SemDiff));
Client.DefaultRequestHeaders.Accept.ParseAdd("application/vnd.github.v3+json");

string authToken = gitHubConfig.AuthenicationToken;
string authUsername = gitHubConfig.Username;
if (!string.IsNullOrEmpty(authToken) || !string.IsNullOrEmpty(authUsername))
{
Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes($"{authUsername}:{authToken}")));
}

RepoFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), nameof(SemDiff), RepoOwner, RepoName);
}

public GitHub(string repoOwner, string repoName, string authUsername, string authToken) : this(repoOwner, repoName)
{
AuthUsername = authUsername;
AuthToken = authToken;
Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes($"{AuthUsername}:{AuthToken}")));
}

public string AuthToken { get; set; }
public string AuthUsername { get; set; }
public string RepoName { get; set; }
public string RepoOwner { get; set; }
public int RequestsRemaining { get; private set; }
public int RequestsLimit { get; private set; }
public HttpClient Client { get; private set; }
public string RepoFolder { get; set; }

private async void APIError(string content)
/// <summary>
/// Makes a request to github to update RequestsRemaining and RequestsLimit
/// </summary>
public Task UpdateLimit()
{
//TODO: implement Error handling

//temp
RequestsRemaining = 0;
return HttpGetAsync("/rate_limit");
}

/// <summary>
Expand All @@ -82,18 +80,34 @@ private async Task<T> HttpGetAsync<T>(string url)
}
catch (Exception e)
{
APIError(content);
throw;
}
}

private async Task<string> HttpGetAsync(string url)
{
//TODO: Handle Errors Here vv
var response = await Client.GetAsync(url);
//Request, but retry once waiting 5 minutes
var response = await Extensions.RetryOnce(() => Client.GetAsync(url), TimeSpan.FromMinutes(5));
IEnumerable<string> headerVal;
if (response.Headers.TryGetValues("X-RateLimit-Limit", out headerVal))
{
RequestsLimit = int.Parse(headerVal.Single());
}
if (response.Headers.TryGetValues("X-RateLimit-Remaining", out headerVal))
{
RequestsRemaining = int.Parse(headerVal.Single());
}
if (!response.IsSuccessStatusCode)
{
//TODO: Implement Check
switch (response.StatusCode)
{
case HttpStatusCode.Unauthorized:
throw new UnauthorizedAccessException("Authentication Failure");
case HttpStatusCode.Forbidden:
throw new UnauthorizedAccessException("Rate Limit Exceeded");
default:
throw new NotImplementedException();
}
}
return await response.Content.ReadAsStringAsync();
}
Expand Down Expand Up @@ -144,20 +158,28 @@ private async Task DownloadFile(int prNum, string path, string sha, bool isAnces
{
var rawText = await HttpGetAsync($@"https://github.com/{RepoOwner}/{RepoName}/raw/{sha}/{path}");
path = path.Replace('/', Path.DirectorySeparatorChar);
var dir = Path.Combine(RepoFolder, $"{prNum}", path);
string dir = GetPathInCache(RepoFolder, prNum, path, isAncestor);
new FileInfo(dir).Directory.Create();
File.WriteAllText(dir, rawText);
}

private static string GetPathInCache(string repofolder, int prNum, string path, bool isAncestor = false)
{
var dir = Path.Combine(repofolder, $"{prNum}", path);

if (isAncestor)
{
dir += ".orig";
}
new FileInfo(dir).Directory.Create();
File.WriteAllText(dir, rawText);

return dir;
}

public class PullRequest
{
public int Number { get; set; }
public string State { get; set; }
public string Title { get; set; }
public bool Locked { get; set; }

[JsonProperty("updated_at")]
Expand All @@ -167,6 +189,16 @@ public class PullRequest
public HeadBase Head { get; set; }
public HeadBase Base { get; set; }
public IList<Files> Files { get; set; }

internal RemoteChanges ToRemoteChanges(string repofolder)
{
return new RemoteChanges
{
Date = Updated,
Title = Title,
Files = Files.Where(f => f.Status == GitHub.Files.StatusEnum.Modified).Where(f => f.Filename.Split('.').Last() == "cs").Select(f => f.ToRemoteFile(repofolder, Number)).ToList(),
};
}
}

public class Files
Expand All @@ -176,6 +208,18 @@ public class Files
[JsonConverter(typeof(StringEnumConverter))]
public StatusEnum Status { get; set; }

internal RemoteFile ToRemoteFile(string repofolder, int num)
{
var baseP = GetPathInCache(repofolder, num, Filename, isAncestor: true);
var fileP = GetPathInCache(repofolder, num, Filename, isAncestor: false);
return new RemoteFile
{
Filename = Filename,
Base = CSharpSyntaxTree.ParseText(File.ReadAllText(baseP), path: baseP),
File = CSharpSyntaxTree.ParseText(File.ReadAllText(fileP), path: fileP)
};
}

//[JsonProperty("raw_url")]
//public string RawUrl { get; set; }
public enum StatusEnum
Expand All @@ -202,41 +246,5 @@ public class HeadBase
public string Ref { get; set; }
public string Sha { get; set; }
}

struct GitHubConfiguration
{
readonly string authenticationToken;
readonly string username;

public GitHubConfiguration(AuthenticationSection section)
{
if (section == null)
{
this.authenticationToken = null;
this.username = null;
}
else
{
this.authenticationToken = section.Authentication.Token;
this.username = section.Authentication.Username;
}
}

public string AuthenicationToken
{
get
{
return this.authenticationToken;
}
}

public string Username
{
get
{
return this.username;
}
}
}
}
}
}
45 changes: 45 additions & 0 deletions SemDiff.Core/GitHubConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using SemDiff.Core.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SemDiff.Core
{
internal struct GitHubConfiguration
{
private readonly string authenticationToken;
private readonly string username;

public GitHubConfiguration(AuthenticationSection section)
{
if (section == null)
{
this.authenticationToken = null;
this.username = null;
}
else
{
this.authenticationToken = section.Authentication.Token;
this.username = section.Authentication.Username;
}
}

public string AuthenicationToken
{
get
{
return this.authenticationToken;
}
}

public string Username
{
get
{
return this.username;
}
}
}
}
5 changes: 3 additions & 2 deletions SemDiff.Core/RemoteChanges.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;

namespace SemDiff.Core
{
Expand All @@ -9,6 +10,6 @@ public class RemoteChanges //TODO: Abstract to File system
{
public string Title { get; set; }
public IEnumerable<RemoteFile> Files { get; set; }
public string Date { get; set; }
public DateTime Date { get; set; }
}
}
3 changes: 3 additions & 0 deletions SemDiff.Core/RemoteFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@ public class RemoteFile //TODO: Abstract to File system
/// The ancestor that the pull request will be merged with
/// </summary>
public SyntaxTree Base { get; set; }

/// <summary>
/// The file from the open pull request
/// </summary>
public SyntaxTree File { get; set; }

public string Filename { get; internal set; }
}
}
Loading

0 comments on commit 8e7c643

Please sign in to comment.