Skip to content

Commit

Permalink
attempt to add semantic diffs
Browse files Browse the repository at this point in the history
  • Loading branch information
goaaats committed Jul 11, 2024
1 parent 2046064 commit f07da16
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 106 deletions.
176 changes: 79 additions & 97 deletions Plogon/BuildProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -440,29 +440,18 @@ private class HasteResponse
[JsonPropertyName("key")]
public string? Key { get; set; }
};

/// <summary>
/// Info about a diff
/// A set of diffs.
/// </summary>
public class PluginDiff
{
/// <summary>
/// URL to reach the diff at
/// </summary>
public string DiffUrl = null!;

/// <summary>
/// How many lines were added
/// </summary>
public int DiffLinesAdded;

/// <summary>
/// How many lines were removed
/// </summary>
public int DiffLinesRemoved;
}

private async Task<PluginDiff> GetPluginDiff(DirectoryInfo workDir, BuildTask task, IEnumerable<BuildTask> tasks)
/// <param name="HosterUrl">Url on git hosting platform.</param>
/// <param name="RegularDiffLink">Regular diff info.</param>
/// <param name="SemanticDiffLink">Semantic diff info.</param>
/// <param name="LinesAdded">Number of lines added.</param>
/// <param name="LinesRemoved">Number of lines removed.</param>
public record PluginDiffSet(string? HosterUrl, string? RegularDiffLink, string? SemanticDiffLink, int LinesAdded, int LinesRemoved);

private async Task<PluginDiffSet> GetPluginDiff(DirectoryInfo workDir, BuildTask task, IEnumerable<BuildTask> tasks)
{
var internalName = task.InternalName;
var haveCommit = task.HaveCommit;
Expand All @@ -485,99 +474,104 @@ private async Task<PluginDiff> GetPluginDiff(DirectoryInfo workDir, BuildTask ta

using var client = new HttpClient();

var result = new PluginDiff();

var url = host.AbsoluteUri.Replace(".git", string.Empty);

string? hosterUrl = null;
switch (host.Host)
{
case "github.com":
// GitHub does not support diffing from 0
if (haveCommit != emptyTree)
result.DiffUrl = $"{url}/compare/{haveCommit}..{wantCommit}";
hosterUrl = $"{url}/compare/{haveCommit}..{wantCommit}";
break;
case "gitlab.com":
result.DiffUrl = $"{url}/-/compare/{haveCommit}...{wantCommit}";
hosterUrl = $"{url}/-/compare/{haveCommit}...{wantCommit}";
break;
}

// Check if relevant commit is still in the repo
if (!await CheckCommitExists(workDir, haveCommit))
haveCommit = emptyTree;

var diffPsi = new ProcessStartInfo("git",
$"diff --submodule=diff {haveCommit}..{wantCommit}")
async Task<string?> MakeAndUploadDiff(bool semantic)
{
RedirectStandardOutput = true,
WorkingDirectory = workDir.FullName,
};
var diffPsi = new ProcessStartInfo("git",
$"diff --submodule=diff {haveCommit}..{wantCommit}")
{
RedirectStandardOutput = true,
WorkingDirectory = workDir.FullName,
};

if (semantic)
diffPsi.Environment["GIT_EXTERNAL_DIFF"] = "difft";

var process = Process.Start(diffPsi);
if (process == null)
throw new Exception("Diff process was null.");
var process = Process.Start(diffPsi);
if (process == null)
throw new Exception("Diff process was null.");

var diffOutput = await process.StandardOutput.ReadToEndAsync();
Log.Verbose("{Args}: {Length}", diffPsi.Arguments, diffOutput.Length);
var diffOutput = await process.StandardOutput.ReadToEndAsync();
Log.Verbose("{Args}: {Length}", diffPsi.Arguments, diffOutput.Length);

await process.WaitForExitAsync();
if (process.ExitCode != 0)
throw new Exception($"Git could not diff: {process.ExitCode} -- {diffPsi.Arguments}");
await process.WaitForExitAsync();
if (process.ExitCode != 0)
throw new Exception($"Git could not diff: {process.ExitCode} -- {diffPsi.Arguments}");

diffPsi = new ProcessStartInfo("git",
$"diff --shortstat --submodule=diff {haveCommit}..{wantCommit}")
{
RedirectStandardOutput = true,
WorkingDirectory = workDir.FullName,
};
if (haveCommit == emptyTree)
return null;

process = Process.Start(diffPsi);
if (process == null)
throw new Exception("Diff process was null.");

var shortstatOutput = await process.StandardOutput.ReadToEndAsync();
var res = await client.PostAsync("https://haste.soulja-boy-told.me/documents", new StringContent(diffOutput));
res.EnsureSuccessStatusCode();

await process.WaitForExitAsync();
if (process.ExitCode != 0)
throw new Exception($"Git could not diff: {process.ExitCode} -- {diffPsi.Arguments}");

var regex = new Regex(@"^\s*(?:(?<numFilesChanged>[0-9]+) files? changed)?(?:, )?(?:(?<numInsertions>[0-9]+) insertions?\(\+\))?(?:, )?(?:(?<numDeletions>[0-9]+) deletions?\(-\))?\s*$");
var match = regex.Match(shortstatOutput);

result.DiffLinesAdded = 0;
result.DiffLinesRemoved = 0;
var json = await res.Content.ReadFromJsonAsync<HasteResponse>();
return $"https://haste.soulja-boy-told.me/{json!.Key}.diff";
}

if (match.Success)
var linesAdded = 0;
var linesRemoved = 0;

// shortstat
{
if (match.Groups.TryGetValue("numInsertions", out var groupInsertions) && int.TryParse(groupInsertions.Value, out var linesAdded))
var diffPsi = new ProcessStartInfo("git",
$"diff --shortstat --submodule=diff {haveCommit}..{wantCommit}")
{
result.DiffLinesAdded = linesAdded;
}
RedirectStandardOutput = true,
WorkingDirectory = workDir.FullName,
};

if (match.Groups.TryGetValue("numDeletions", out var groupDeletions) && int.TryParse(groupDeletions.Value, out var linesRemoved))
{
result.DiffLinesRemoved = linesRemoved;
}
}
var process = Process.Start(diffPsi);
if (process == null)
throw new Exception("Diff process was null.");

Log.Verbose("{Args}: {Output} - {Length}, +{LinesAdded} -{LinesRemoved}", diffPsi.Arguments, shortstatOutput, shortstatOutput.Length, result.DiffLinesAdded, result.DiffLinesRemoved);
var shortstatOutput = await process.StandardOutput.ReadToEndAsync();

if (!string.IsNullOrEmpty(result.DiffUrl))
return result;

if (haveCommit == emptyTree)
{
result.DiffUrl = url;
return result;
}

var res = await client.PostAsync("https://haste.soulja-boy-told.me/documents", new StringContent(diffOutput));
res.EnsureSuccessStatusCode();
await process.WaitForExitAsync();
if (process.ExitCode != 0)
throw new Exception($"Git could not diff: {process.ExitCode} -- {diffPsi.Arguments}");


var json = await res.Content.ReadFromJsonAsync<HasteResponse>();
var regex = new Regex(@"^\s*(?:(?<numFilesChanged>[0-9]+) files? changed)?(?:, )?(?:(?<numInsertions>[0-9]+) insertions?\(\+\))?(?:, )?(?:(?<numDeletions>[0-9]+) deletions?\(-\))?\s*$");
var match = regex.Match(shortstatOutput);

result.DiffUrl = $"https://haste.soulja-boy-told.me/{json!.Key}.diff";
if (match.Success)
{
if (!match.Groups.TryGetValue("numInsertions", out var groupInsertions) && int.TryParse(groupInsertions?.Value, out linesAdded))
{
Log.Error("Could not parse insertions");
}

return result;
if (!match.Groups.TryGetValue("numDeletions", out var groupDeletions) && int.TryParse(groupDeletions?.Value, out linesRemoved))
{
Log.Error("Could not parse deletions");
}
}

Log.Verbose("{Args}: {Output} - {Length}, +{LinesAdded} -{LinesRemoved}", diffPsi.Arguments, shortstatOutput, shortstatOutput.Length, linesAdded, linesRemoved);
}

var diffNormal = await MakeAndUploadDiff(false);
var diffSemantic = await MakeAndUploadDiff(true);

return new PluginDiffSet(hosterUrl, diffNormal, diffSemantic, linesAdded, linesRemoved);
}

private async Task<bool> CheckCommitExists(DirectoryInfo workDir, string commit)
Expand Down Expand Up @@ -668,12 +662,10 @@ public class BuildResult
/// <param name="diff">diff url</param>
/// <param name="version">plugin version</param>
/// <param name="task">processed task</param>
public BuildResult(bool success, PluginDiff? diff, string? version, BuildTask task)
public BuildResult(bool success, PluginDiffSet? diff, string? version, BuildTask task)
{
this.Success = success;
this.DiffUrl = diff?.DiffUrl;
this.DiffLinesAdded = diff?.DiffLinesAdded;
this.DiffLinesRemoved = diff?.DiffLinesRemoved;
this.Diff = diff;
this.Version = version;
this.PreviousVersion = task.HaveVersion;
this.Task = task;
Expand All @@ -687,7 +679,7 @@ public BuildResult(bool success, PluginDiff? diff, string? version, BuildTask ta
/// <summary>
/// Where the diff is
/// </summary>
public string? DiffUrl { get; private set; }
public PluginDiffSet? Diff { get; private set; }

/// <summary>
/// The version of the plugin artifact
Expand All @@ -703,16 +695,6 @@ public BuildResult(bool success, PluginDiff? diff, string? version, BuildTask ta
/// The task that was processed
/// </summary>
public BuildTask Task { get; private set; }

/// <summary>
/// The amount of lines added, if available.
/// </summary>
public int? DiffLinesAdded { get; private set; }

/// <summary>
/// The amount of lines removed, if available.
/// </summary>
public int? DiffLinesRemoved { get; private set; }
}

private class LegacyPluginManifest
Expand Down
27 changes: 18 additions & 9 deletions Plogon/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -296,16 +296,25 @@ static async Task Main(DirectoryInfo outputFolder, DirectoryInfo manifestFolder,
var status = await buildProcessor.ProcessTask(task, mode == ModeOfOperation.Commit, changelog, tasks);
statuses.Add(status);

var mainDiffUrl = status.Diff?.HosterUrl ?? status.Diff?.RegularDiffLink;

if (status.Success)
{
Log.Information("Built: {Name} - {Sha} - {DiffUrl} +{LinesAdded} -{LinesRemoved}", task.InternalName,
task.Manifest.Plugin.Commit, status.DiffUrl ?? "null", status.DiffLinesAdded ?? -1, status.DiffLinesRemoved ?? -1);
task.Manifest.Plugin.Commit, mainDiffUrl ?? "null", status.Diff?.LinesAdded ?? -1, status.Diff?.LinesRemoved ?? -1);


var linesAddedText = status.Diff?.LinesAdded == null ? "?" : status.Diff.LinesAdded.ToString();
var prevVersionText = string.IsNullOrEmpty(status.PreviousVersion)
? string.Empty
: $", prev. {status.PreviousVersion}";
var diffLink = status.DiffUrl == url ? $"[Repo]({url}) <sup><sup>(New plugin)</sup></sup>" :
$"[Diff]({status.DiffUrl}) <sup><sub>({status.DiffLinesAdded} lines{prevVersionText})</sub></sup>";
var diffLink = mainDiffUrl == null ? $"[Repo]({url}) <sup><sup>(New plugin)</sup></sup>" :
$"[Diff]({mainDiffUrl}) <sup><sub>({linesAddedText} lines{prevVersionText})</sub></sup>";

if (status.Diff?.SemanticDiffLink != null)
{
diffLink += $" - [Semantic]({status.Diff.SemanticDiffLink})";
}

// We don't want to indicate success for continuous builds
if (mode != ModeOfOperation.Continuous)
Expand All @@ -328,15 +337,15 @@ static async Task Main(DirectoryInfo outputFolder, DirectoryInfo manifestFolder,
await webservices.RegisterPrNumber(task.InternalName, task.Manifest.Plugin.Commit,
prNumber);

if (status.DiffLinesAdded.HasValue)
if (status.Diff != null)
{
if (status.DiffLinesAdded > 1000)
if (status.Diff.LinesAdded > 1000)
{
prLabels &= ~GitHubApi.PrLabel.SizeSmall;
prLabels &= ~GitHubApi.PrLabel.SizeMid;
prLabels |= GitHubApi.PrLabel.SizeLarge;
}
else if (status.DiffLinesAdded > 400 && !prLabels.HasFlag(GitHubApi.PrLabel.SizeLarge))
else if (status.Diff.LinesAdded > 400 && !prLabels.HasFlag(GitHubApi.PrLabel.SizeLarge))
{
prLabels &= ~GitHubApi.PrLabel.SizeSmall;
prLabels |= GitHubApi.PrLabel.SizeMid;
Expand Down Expand Up @@ -370,8 +379,8 @@ await webservices.StagePluginBuild(new WebServices.StagedPluginInfo
PrNumber = prInt,
Changelog = changelog,
IsInitialRelease = task.IsNewPlugin,
DiffLinesAdded = status.DiffLinesAdded,
DiffLinesRemoved = status.DiffLinesRemoved,
DiffLinesAdded = status.Diff?.LinesAdded,
DiffLinesRemoved = status.Diff?.LinesRemoved,
});
}
}
Expand All @@ -381,7 +390,7 @@ await webservices.StagePluginBuild(new WebServices.StagedPluginInfo
task.Manifest.Plugin.Commit);

buildsMd.AddRow("", $"{task.InternalName} [{task.Channel}]", fancyCommit,
$"Build failed ([Diff]({status.DiffUrl}))");
$"Build failed ([Diff]({mainDiffUrl}))");
numFailed++;
}
}
Expand Down
1 change: 1 addition & 0 deletions Plogon/Repo/PluginRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ public void RemovePlugin(string channelName, string plugin)
/// <param name="plugin">The internalname of the plugin</param>
/// <param name="haveCommit">Commit that is now have</param>
/// <param name="effectiveVersion">New version of the plugin</param>
/// <param name="minimumVersion">Minimum version Dalamud should still try to load.</param>
/// <param name="changelog">Plugin changelog</param>
public void UpdatePluginHave(string channelName, string plugin, string haveCommit, string effectiveVersion, string? minimumVersion, string? changelog)
{
Expand Down

0 comments on commit f07da16

Please sign in to comment.