Skip to content

Commit

Permalink
Separate the logic for get the pull-request info from the url.
Browse files Browse the repository at this point in the history
  • Loading branch information
andy840119 committed Jan 14, 2024
1 parent 700cd2a commit b180bd4
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 43 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (c) andy840119 <andy840119@gmail.com>. Licensed under the GPL Licence.
// See the LICENCE file in the repository root for full licence text.

using System.Linq;
using NUnit.Framework;
using osu.Game.Rulesets.Karaoke.Overlays.Changelog;

namespace osu.Game.Rulesets.Karaoke.Tests.Overlays.Changelog;

public class ChangelogPullRequestInfoTest
{
[TestCase("#2152@andy840119", new[] { 2152 }, new[] { "andy840119" })]
[TestCase("#2152", new[] { 2152 }, new string[] { })]
[TestCase("@andy840119", new int[] { }, new[] { "andy840119" })]
[TestCase("#2152#2153", new[] { 2152, 2153 }, new string[] { })]
[TestCase("#2152#2152", new[] { 2152 }, new string[] { })]
[TestCase("@andy@andy840119", new int[] { }, new[] { "andy", "andy840119" })]
[TestCase("@andy840119@andy840119", new int[] { }, new[] { "andy840119" })]
[TestCase("https://raw.githubusercontent.com/karaoke-dev/karaoke-dev.github.io/master/content/changelog/2023.1212/#2152@andy840119", new[] { 2152 }, new[] { "andy840119" })] // the actual data that will be get in this method.
public void TestGetPullRequestInfoFromLink(string url, int[] expectedPrs, string[] expectedUserNames)
{
var result = ChangelogPullRequestInfo.GetPullRequestInfoFromLink("karaoke", url)!;

Assert.AreEqual(expectedPrs, result.PullRequests.Select(x => x.Number));
Assert.AreEqual(expectedUserNames, result.Users.Select(x => x.UserName));
}

[TestCase("unknown_repo", "#2152@andy840119")] // "unknown_repo" does not in the repo list.
[TestCase("karaoke", "")] // there's no pr number or username.
[TestCase("karaoke", "hello")] // invalid pr number or username.
[TestCase("karaoke", "#aaa")] // invalid pr number.
public void TestTestGetPullRequestInfoFromLinkWithNull(string link, string url)
{
var result = ChangelogPullRequestInfo.GetPullRequestInfoFromLink(link, url);
Assert.IsNull(result);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,13 @@
// See the LICENCE file in the repository root for full licence text.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Markdig.Syntax.Inlines;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Layout;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers.Markdown;
using osu.Game.Rulesets.Karaoke.Extensions;
using osu.Game.Rulesets.Karaoke.Online.API.Requests.Responses;
using osuTK;

Expand Down Expand Up @@ -40,78 +37,51 @@ public partial class ChangeLogMarkdownTextFlowContainer : OsuMarkdownTextFlowCon
{
protected override void AddImage(LinkInline linkInline) => AddDrawable(new ChangeLogMarkdownImage(linkInline));

private readonly IDictionary<string, string> githubUrls = new Dictionary<string, string>
{
{ "karaoke", "https://github.com/karaoke-dev/karaoke/" },
{ "edge", "https://github.com/karaoke-dev/karaoke/" },
{ "github.io", "https://github.com/karaoke-dev/karaoke-dev.github.io/" },
{ "launcher", "https://github.com/karaoke-dev/launcher/" },
{ "sample", "https://github.com/karaoke-dev/sample-beatmap/" },
{ "microphone-package", "https://github.com/karaoke-dev/osu-framework-microphone/" },
{ "font-package", "https://github.com/karaoke-dev/osu-framework-font/" },
};

protected override void AddLinkText(string text, LinkInline linkInline)
{
if (linkInline.Url == null)
return;

if (!githubUrls.ContainsKey(text))
var pullRequestInfo = ChangelogPullRequestInfo.GetPullRequestInfoFromLink(text, linkInline.Url);

if (pullRequestInfo == null)
{
base.AddLinkText(text, linkInline);
return;
}

var baseUri = new Uri(githubUrls[text]);

// Get hash tag with number
const string issue_regex = "#(?<issue>[0-9]+)|@(?<username>[0-9A-z]+)";
var result = Regex.Matches(linkInline.Url, issue_regex, RegexOptions.IgnoreCase);

if (!result.Any())
return;
var pullRequests = pullRequestInfo.PullRequests;
var users = pullRequestInfo.Users;

// add issue if has user
string[] issues = result.Select(x => x.GetGroupValue<string>("issue")).Where(x => !string.IsNullOrEmpty(x)).ToArray();

if (issues.Any())
if (pullRequests.Any())
{
AddText("(");

foreach (string issue in issues)
foreach (var pullRequest in pullRequests)
{
if (string.IsNullOrEmpty(issue))
continue;

AddDrawable(new OsuMarkdownLinkText($"{text}#{issue}", new LinkInline
AddDrawable(new OsuMarkdownLinkText($"{text}#{pullRequest.Number}", new LinkInline
{
Url = new Uri(baseUri, $"pull/{issue}").AbsoluteUri,
Url = pullRequest.Url,
}));

if (issue != issues.LastOrDefault())
if (pullRequest != pullRequests.LastOrDefault())
AddText(", ");
}

AddText(")");
}

// add use name if has user
var usernames = result.Select(x => x.GetGroupValue<string>("username")).Where(x => !string.IsNullOrEmpty(x));

foreach (string user in usernames)
foreach (var user in users)
{
if (string.IsNullOrEmpty(user))
return;

var textScale = new Vector2(0.7f);
AddText(" by ", t =>
{
t.Scale = textScale;
t.Padding = new MarginPadding { Top = 6 };
});
AddDrawable(new UserLinkText(user, new LinkInline
AddDrawable(new UserLinkText(user.UserName, new LinkInline
{
Url = $"https://github.com/{user}",
Url = user.UserUrl,
})
{
Scale = textScale,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// Copyright (c) andy840119 <andy840119@gmail.com>. Licensed under the GPL Licence.
// See the LICENCE file in the repository root for full licence text.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using osu.Game.Rulesets.Karaoke.Extensions;

namespace osu.Game.Rulesets.Karaoke.Overlays.Changelog;

public class ChangelogPullRequestInfo
{
private static readonly IDictionary<string, string> repo_urls = new Dictionary<string, string>
{
{ "karaoke", "https://github.com/karaoke-dev/karaoke/" },
{ "edge", "https://github.com/karaoke-dev/karaoke/" },
{ "github.io", "https://github.com/karaoke-dev/karaoke-dev.github.io/" },
{ "launcher", "https://github.com/karaoke-dev/launcher/" },
{ "sample", "https://github.com/karaoke-dev/sample-beatmap/" },
{ "microphone-package", "https://github.com/karaoke-dev/osu-framework-microphone/" },
{ "font-package", "https://github.com/karaoke-dev/osu-framework-font/" },
};

public PullRequestInfo[] PullRequests { get; set; } = Array.Empty<PullRequestInfo>();

public UserInfo[] Users { get; set; } = Array.Empty<UserInfo>();

public class PullRequestInfo
{
public int Number { get; set; }

public string Url { get; set; } = string.Empty;
}

public class UserInfo
{
public string UserName { get; set; } = string.Empty;

public string UserUrl => $"https://github.com/{UserName}";
}

/// <summary>
/// Trying to parse the pull-request info from the url.
/// </summary>
/// <example>
/// #2152@andy840119<br/>
/// #2152<br/>
/// #2152#2153<br/>
/// @andy840119<br/>
/// @andy@andy840119
/// </example>
/// <param name="text">Link text</param>
/// <param name="url">Link url</param>
/// <returns></returns>
public static ChangelogPullRequestInfo? GetPullRequestInfoFromLink(string text, string url)
{
if (!repo_urls.ContainsKey(text))
return null;

const string pull_request_key = "pull_request";
const string username_key = "username";
const string pull_request_regex = $"#(?<{pull_request_key}>[0-9]+)|@(?<{username_key}>[0-9A-z]+)";

// note: should have at least one pr number or one username,
var result = Regex.Matches(url, pull_request_regex, RegexOptions.IgnoreCase);
if (!result.Any())
return null;

// get pull-request or username
var prs = result.Select(x => x.GetGroupValue<string>(pull_request_key))
.Where(x => !string.IsNullOrEmpty(x))
.Distinct();
var usernames = result.Select(x => x.GetGroupValue<string>(username_key))
.Where(x => !string.IsNullOrEmpty(x))
.Distinct();

return new ChangelogPullRequestInfo
{
PullRequests = prs.Select(x => generatePullRequestInfo(repo_urls[text], x)).ToArray(),
Users = usernames.Select(generateUserInfo).ToArray(),
};

static PullRequestInfo generatePullRequestInfo(string url, string pr) =>
new()
{
Number = int.Parse(pr),
Url = new Uri(new Uri(url), $"pull/{pr}").AbsoluteUri,
};

static UserInfo generateUserInfo(string username) =>
new()
{
UserName = username,
};
}
}

0 comments on commit b180bd4

Please sign in to comment.