From 26127efa2faa0607e563020da57d542e077f53c6 Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Sat, 8 Mar 2014 16:06:28 +1100 Subject: [PATCH 01/10] stubbed prototype method to support comparing two commits --- Octokit/Clients/IRepositoriesClient.cs | 11 +++++++++++ Octokit/Clients/RepositoriesClient.cs | 17 +++++++++++++++++ Octokit/Helpers/ApiUrls.cs | 15 +++++++++++++++ Octokit/Helpers/StringExtensions.cs | 5 +++++ Octokit/Models/Response/CompareResult.cs | 19 +++++++++++++++++++ Octokit/Octokit-Mono.csproj | 1 + Octokit/Octokit-MonoAndroid.csproj | 1 + Octokit/Octokit-Monotouch.csproj | 1 + Octokit/Octokit-netcore45.csproj | 1 + Octokit/Octokit.csproj | 1 + 10 files changed, 72 insertions(+) create mode 100644 Octokit/Models/Response/CompareResult.cs diff --git a/Octokit/Clients/IRepositoriesClient.cs b/Octokit/Clients/IRepositoriesClient.cs index 2989c61040..89ae418772 100644 --- a/Octokit/Clients/IRepositoriesClient.cs +++ b/Octokit/Clients/IRepositoriesClient.cs @@ -264,5 +264,16 @@ public interface IRepositoriesClient /// New values to update the repository with /// The updated Task Edit(string owner, string name, RepositoryUpdate update); + + /// + /// + /// + /// + /// + /// + /// + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "base")] + Task Compare(string owner, string name, string @base, string head); } } diff --git a/Octokit/Clients/RepositoriesClient.cs b/Octokit/Clients/RepositoriesClient.cs index f46e65bd7d..2c44c10b89 100644 --- a/Octokit/Clients/RepositoriesClient.cs +++ b/Octokit/Clients/RepositoriesClient.cs @@ -426,5 +426,22 @@ public Task GetBranch(string owner, string repositoryName, string branch return ApiConnection.Get(ApiUrls.RepoBranch(owner, repositoryName, branchName)); } + + /// + /// + /// + /// + /// + /// + /// + /// + public Task Compare(string owner, string name, string @base, string head) + { + Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); + Ensure.ArgumentNotNullOrEmptyString(name, "repositoryName"); + Ensure.ArgumentNotNullOrEmptyString(@base, "branchName"); + + return ApiConnection.Get(ApiUrls.RepoCompare(owner, name, @base, head)); + } } } diff --git a/Octokit/Helpers/ApiUrls.cs b/Octokit/Helpers/ApiUrls.cs index d334c34ffb..c422634c05 100644 --- a/Octokit/Helpers/ApiUrls.cs +++ b/Octokit/Helpers/ApiUrls.cs @@ -1049,6 +1049,21 @@ public static Uri RepositoryTags(string owner, string name) return "repos/{0}/{1}/tags".FormatUri(owner, name); } + /// + /// Returns the for comparing two commits. + /// + /// The owner of the repository + /// The name of the repository + /// The base commit + /// The head commit + /// + public static Uri RepoCompare(string owner, string repositoryName, string @base, string head) + { + var encodedBase = @base.UriEncode(); + var encodedHead = head.UriEncode(); + return "repos/{0}/{1}/compare/{2}...{3}".FormatUri(owner, repositoryName, encodedBase, encodedHead); + } + /// /// Returns the for a repository branch. /// diff --git a/Octokit/Helpers/StringExtensions.cs b/Octokit/Helpers/StringExtensions.cs index 7276d7afa3..cc8f1705f8 100644 --- a/Octokit/Helpers/StringExtensions.cs +++ b/Octokit/Helpers/StringExtensions.cs @@ -26,6 +26,11 @@ public static Uri FormatUri(this string pattern, params object[] args) return new Uri(string.Format(CultureInfo.InvariantCulture, pattern, args), UriKind.Relative); } + public static string UriEncode(this string input) + { + return System.Net.WebUtility.UrlEncode(input); + } + static readonly Regex _optionalQueryStringRegex = new Regex("\\{\\?([^}]+)\\}"); public static Uri ExpandUriTemplate(this string template, object values) { diff --git a/Octokit/Models/Response/CompareResult.cs b/Octokit/Models/Response/CompareResult.cs new file mode 100644 index 0000000000..65e834ac8f --- /dev/null +++ b/Octokit/Models/Response/CompareResult.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; + +namespace Octokit +{ + public class CompareResult + { + public string Url { get; set; } + public string HtmlUrl { get; set; } + public string PermalinkUrl { get; set; } + public string DiffUrl { get; set; } + public string PatchUrl { get; set; } + public Commit BaseCommit { get; set; } + public string Status { get; set; } + public int AheadBy { get; set; } + public int BehindBy { get; set; } + public int TotalCommits { get; set; } + public IReadOnlyCollection Commits { get; set; } + } +} diff --git a/Octokit/Octokit-Mono.csproj b/Octokit/Octokit-Mono.csproj index 9fbca9f52b..cd62c96ce3 100644 --- a/Octokit/Octokit-Mono.csproj +++ b/Octokit/Octokit-Mono.csproj @@ -310,6 +310,7 @@ + \ No newline at end of file diff --git a/Octokit/Octokit-MonoAndroid.csproj b/Octokit/Octokit-MonoAndroid.csproj index cb66cd52b8..c1630543c1 100644 --- a/Octokit/Octokit-MonoAndroid.csproj +++ b/Octokit/Octokit-MonoAndroid.csproj @@ -321,6 +321,7 @@ + \ No newline at end of file diff --git a/Octokit/Octokit-Monotouch.csproj b/Octokit/Octokit-Monotouch.csproj index 5a1d9522ca..603a097ff0 100644 --- a/Octokit/Octokit-Monotouch.csproj +++ b/Octokit/Octokit-Monotouch.csproj @@ -316,6 +316,7 @@ + \ No newline at end of file diff --git a/Octokit/Octokit-netcore45.csproj b/Octokit/Octokit-netcore45.csproj index aba7eb5d71..14929305c2 100644 --- a/Octokit/Octokit-netcore45.csproj +++ b/Octokit/Octokit-netcore45.csproj @@ -308,6 +308,7 @@ + diff --git a/Octokit/Octokit.csproj b/Octokit/Octokit.csproj index 51c1de2d91..076d7c9384 100644 --- a/Octokit/Octokit.csproj +++ b/Octokit/Octokit.csproj @@ -64,6 +64,7 @@ + From 438f7f66a97aedf00674635959b9179858920a1e Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Sat, 8 Mar 2014 18:43:54 +1100 Subject: [PATCH 02/10] added reactive client and tidied up xml-docs --- .../Clients/IObservableRepositoriesClient.cs | 11 +++++++++++ .../Clients/ObservableRepositoriesClient.cs | 13 +++++++++++++ Octokit/Clients/IRepositoriesClient.cs | 12 ++++++------ Octokit/Clients/RepositoriesClient.cs | 10 +++++----- Octokit/Models/Response/CompareResult.cs | 14 +++++++++++++- 5 files changed, 48 insertions(+), 12 deletions(-) diff --git a/Octokit.Reactive/Clients/IObservableRepositoriesClient.cs b/Octokit.Reactive/Clients/IObservableRepositoriesClient.cs index 639acde19d..54ee223c60 100644 --- a/Octokit.Reactive/Clients/IObservableRepositoriesClient.cs +++ b/Octokit.Reactive/Clients/IObservableRepositoriesClient.cs @@ -213,6 +213,17 @@ public interface IObservableRepositoriesClient /// The updated IObservable Edit(string owner, string name, RepositoryUpdate update); + /// + /// Compare two references in a repository + /// + /// The owner of the repository + /// The name of the repository + /// The reference to use as the base commit + /// The reference to use as the head commit + /// + [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "base")] + IObservable Compare(string owner, string name, string @base, string @head); + /// /// A client for GitHub's Repo Collaborators. /// diff --git a/Octokit.Reactive/Clients/ObservableRepositoriesClient.cs b/Octokit.Reactive/Clients/ObservableRepositoriesClient.cs index 1374973963..a6f99e4bf3 100644 --- a/Octokit.Reactive/Clients/ObservableRepositoriesClient.cs +++ b/Octokit.Reactive/Clients/ObservableRepositoriesClient.cs @@ -328,6 +328,19 @@ public IObservable Edit(string owner, string name, RepositoryUpdate return _client.Edit(owner, name, update).ToObservable(); } + /// + /// Compare two references in a repository + /// + /// The owner of the repository + /// The name of the repository + /// The reference to use as the base commit + /// The reference to use as the head commit + /// + public IObservable Compare(string owner, string name, string @base, string head) + { + return _client.Compare(owner, name, @base, head).ToObservable(); + } + /// /// A client for GitHub's Repo Collaborators. /// diff --git a/Octokit/Clients/IRepositoriesClient.cs b/Octokit/Clients/IRepositoriesClient.cs index 89ae418772..15996b129e 100644 --- a/Octokit/Clients/IRepositoriesClient.cs +++ b/Octokit/Clients/IRepositoriesClient.cs @@ -266,14 +266,14 @@ public interface IRepositoriesClient Task Edit(string owner, string name, RepositoryUpdate update); /// - /// + /// Compare two references in a repository /// - /// - /// - /// - /// + /// The owner of the repository + /// The name of the repository + /// The reference to use as the base commit + /// The reference to use as the head commit /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "base")] + [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "base")] Task Compare(string owner, string name, string @base, string head); } } diff --git a/Octokit/Clients/RepositoriesClient.cs b/Octokit/Clients/RepositoriesClient.cs index 2c44c10b89..5fab5ea7f5 100644 --- a/Octokit/Clients/RepositoriesClient.cs +++ b/Octokit/Clients/RepositoriesClient.cs @@ -428,12 +428,12 @@ public Task GetBranch(string owner, string repositoryName, string branch } /// - /// + /// Compare two references in a repository /// - /// - /// - /// - /// + /// The owner of the repository + /// The name of the repository + /// The reference to use as the base commit + /// The reference to use as the head commit /// public Task Compare(string owner, string name, string @base, string head) { diff --git a/Octokit/Models/Response/CompareResult.cs b/Octokit/Models/Response/CompareResult.cs index 65e834ac8f..874d0f19f1 100644 --- a/Octokit/Models/Response/CompareResult.cs +++ b/Octokit/Models/Response/CompareResult.cs @@ -1,7 +1,11 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; namespace Octokit { + [DebuggerDisplay("{DebuggerDisplay,nq}")] public class CompareResult { public string Url { get; set; } @@ -15,5 +19,13 @@ public class CompareResult public int BehindBy { get; set; } public int TotalCommits { get; set; } public IReadOnlyCollection Commits { get; set; } + + internal string DebuggerDisplay + { + get + { + return String.Format(CultureInfo.InvariantCulture, "Status: {0} Ahead By: {1}, Behind By: {2}", Status, AheadBy, BehindBy); + } + } } } From ba82c4ea6888f7117ebad752831e2f8a4d8529c9 Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Sat, 8 Mar 2014 19:01:33 +1100 Subject: [PATCH 03/10] added unit tests --- .../Clients/RepositoriesClientTests.cs | 47 +++++++++++++++++++ Octokit/Clients/RepositoriesClient.cs | 3 +- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/Octokit.Tests/Clients/RepositoriesClientTests.cs b/Octokit.Tests/Clients/RepositoriesClientTests.cs index 0650553584..9f7b181221 100644 --- a/Octokit.Tests/Clients/RepositoriesClientTests.cs +++ b/Octokit.Tests/Clients/RepositoriesClientTests.cs @@ -557,5 +557,52 @@ public void EnsuresNonNullArguments() Assert.Throws(() => client.Edit("owner", "", update)); } } + + public class TheCompareMethod + { + [Fact] + public void EnsureNonNullArguments() + { + var client = new RepositoriesClient(Substitute.For()); + + Assert.Throws(() => client.Compare(null, "repo", "base", "head")); + Assert.Throws(() => client.Compare("", "repo", "base", "head")); + + Assert.Throws(() => client.Compare("owner", null, "base", "head")); + Assert.Throws(() => client.Compare("owner", "", "base", "head")); + + Assert.Throws(() => client.Compare("owner", "repo", null, "head")); + Assert.Throws(() => client.Compare("owner", "repo", "", "head")); + + Assert.Throws(() => client.Compare("owner", "repo", "base", null)); + Assert.Throws(() => client.Compare("owner", "repo", "base", "")); + } + + [Fact] + public void GetsCorrectUrl() + { + var connection = Substitute.For(); + + var client = new RepositoriesClient(connection); + + client.Compare("owner", "repo", "base", "head"); + + connection.Received() + .Get(Arg.Is(u => u.ToString() == "repos/owner/repo/compare/base...head"), null); + } + + [Fact] + public void EncodesUrl() + { + var connection = Substitute.For(); + + var client = new RepositoriesClient(connection); + + client.Compare("owner", "repo", "base", "shiftkey/my-cool-branch"); + + connection.Received() + .Get(Arg.Is(u => u.ToString() == "repos/owner/repo/compare/base...shiftkey%2Fmy-cool-branch"), null); + } + } } } diff --git a/Octokit/Clients/RepositoriesClient.cs b/Octokit/Clients/RepositoriesClient.cs index 5fab5ea7f5..4806ab878f 100644 --- a/Octokit/Clients/RepositoriesClient.cs +++ b/Octokit/Clients/RepositoriesClient.cs @@ -439,7 +439,8 @@ public Task Compare(string owner, string name, string @base, stri { Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); Ensure.ArgumentNotNullOrEmptyString(name, "repositoryName"); - Ensure.ArgumentNotNullOrEmptyString(@base, "branchName"); + Ensure.ArgumentNotNullOrEmptyString(@base, "base"); + Ensure.ArgumentNotNullOrEmptyString(head, "head"); return ApiConnection.Get(ApiUrls.RepoCompare(owner, name, @base, head)); } From e6be0ad334f0ca353146aa804517c4346661e35a Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Sat, 8 Mar 2014 19:11:59 +1100 Subject: [PATCH 04/10] moved function out to separate client --- .../Clients/ObservableRepositoriesClient.cs | 2 +- .../Clients/RepositoriesClientTests.cs | 12 ++++----- Octokit/Clients/IRepositoriesClient.cs | 19 ++++++------- Octokit/Clients/IRepositoryCommitsClient.cs | 19 +++++++++++++ Octokit/Clients/RepositoriesClient.cs | 27 +++++++------------ Octokit/Clients/RepositoryCommitsClient.cs | 24 +++++++++++++++++ Octokit/Octokit-Mono.csproj | 2 ++ Octokit/Octokit-MonoAndroid.csproj | 2 ++ Octokit/Octokit-Monotouch.csproj | 2 ++ Octokit/Octokit-netcore45.csproj | 2 ++ Octokit/Octokit.csproj | 2 ++ 11 files changed, 77 insertions(+), 36 deletions(-) create mode 100644 Octokit/Clients/IRepositoryCommitsClient.cs create mode 100644 Octokit/Clients/RepositoryCommitsClient.cs diff --git a/Octokit.Reactive/Clients/ObservableRepositoriesClient.cs b/Octokit.Reactive/Clients/ObservableRepositoriesClient.cs index a6f99e4bf3..d84588c23f 100644 --- a/Octokit.Reactive/Clients/ObservableRepositoriesClient.cs +++ b/Octokit.Reactive/Clients/ObservableRepositoriesClient.cs @@ -338,7 +338,7 @@ public IObservable Edit(string owner, string name, RepositoryUpdate /// public IObservable Compare(string owner, string name, string @base, string head) { - return _client.Compare(owner, name, @base, head).ToObservable(); + return _client.Commits.Compare(owner, name, @base, head).ToObservable(); } /// diff --git a/Octokit.Tests/Clients/RepositoriesClientTests.cs b/Octokit.Tests/Clients/RepositoriesClientTests.cs index 9f7b181221..d995cffbbc 100644 --- a/Octokit.Tests/Clients/RepositoriesClientTests.cs +++ b/Octokit.Tests/Clients/RepositoriesClientTests.cs @@ -35,7 +35,7 @@ public async Task EnsuresNonNullArguments() await AssertEx.Throws(async () => await client.Create(null)); await AssertEx.Throws(async () => await client.Create(new NewRepository { Name = null })); } - + [Fact] public void UsesTheUserReposUrl() { @@ -345,9 +345,9 @@ public async Task ReturnsReadme() var readme = await reposEndpoint.GetReadme("fake", "repo"); Assert.Equal("README.md", readme.Name); - connection.Received().Get(Arg.Is(u => u.ToString() == "repos/fake/repo/readme"), + connection.Received().Get(Arg.Is(u => u.ToString() == "repos/fake/repo/readme"), null); - connection.DidNotReceive().GetHtml(Arg.Is(u => u.ToString() == "https://github.example.com/readme"), + connection.DidNotReceive().GetHtml(Arg.Is(u => u.ToString() == "https://github.example.com/readme"), null); var htmlReadme = await readme.GetHtmlContent(); Assert.Equal("README", htmlReadme); @@ -563,7 +563,7 @@ public class TheCompareMethod [Fact] public void EnsureNonNullArguments() { - var client = new RepositoriesClient(Substitute.For()); + var client = new RepositoryCommitsClient(Substitute.For()); Assert.Throws(() => client.Compare(null, "repo", "base", "head")); Assert.Throws(() => client.Compare("", "repo", "base", "head")); @@ -583,7 +583,7 @@ public void GetsCorrectUrl() { var connection = Substitute.For(); - var client = new RepositoriesClient(connection); + var client = new RepositoryCommitsClient(connection); client.Compare("owner", "repo", "base", "head"); @@ -596,7 +596,7 @@ public void EncodesUrl() { var connection = Substitute.For(); - var client = new RepositoriesClient(connection); + var client = new RepositoryCommitsClient(connection); client.Compare("owner", "repo", "base", "shiftkey/my-cool-branch"); diff --git a/Octokit/Clients/IRepositoriesClient.cs b/Octokit/Clients/IRepositoriesClient.cs index 15996b129e..175bc203f2 100644 --- a/Octokit/Clients/IRepositoriesClient.cs +++ b/Octokit/Clients/IRepositoriesClient.cs @@ -176,6 +176,14 @@ public interface IRepositoriesClient /// IStatisticsClient Statistics { get; } + /// + /// Client for GitHub's Repository Commits API + /// + /// + /// See the Commits API documentation for more details + /// + IRepositoryCommitsClient Commits { get; } + /// /// Gets all the branches for the specified repository. /// @@ -264,16 +272,5 @@ public interface IRepositoriesClient /// New values to update the repository with /// The updated Task Edit(string owner, string name, RepositoryUpdate update); - - /// - /// Compare two references in a repository - /// - /// The owner of the repository - /// The name of the repository - /// The reference to use as the base commit - /// The reference to use as the head commit - /// - [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "base")] - Task Compare(string owner, string name, string @base, string head); } } diff --git a/Octokit/Clients/IRepositoryCommitsClient.cs b/Octokit/Clients/IRepositoryCommitsClient.cs new file mode 100644 index 0000000000..567792b937 --- /dev/null +++ b/Octokit/Clients/IRepositoryCommitsClient.cs @@ -0,0 +1,19 @@ +using System.Diagnostics.CodeAnalysis; +using System.Threading.Tasks; + +namespace Octokit +{ + public interface IRepositoryCommitsClient + { + /// + /// Compare two references in a repository + /// + /// The owner of the repository + /// The name of the repository + /// The reference to use as the base commit + /// The reference to use as the head commit + /// + [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "base")] + Task Compare(string owner, string name, string @base, string head); + } +} diff --git a/Octokit/Clients/RepositoriesClient.cs b/Octokit/Clients/RepositoriesClient.cs index 4806ab878f..fc22e45922 100644 --- a/Octokit/Clients/RepositoriesClient.cs +++ b/Octokit/Clients/RepositoriesClient.cs @@ -28,6 +28,7 @@ public RepositoriesClient(IApiConnection apiConnection) : base(apiConnection) Deployment = new DeploymentsClient(apiConnection); PullRequest = new PullRequestsClient(apiConnection); RepositoryComments = new RepositoryCommentsClient(apiConnection); + Commits = new RepositoryCommitsClient(apiConnection); } /// @@ -279,6 +280,14 @@ public Task GetReadmeHtml(string owner, string name) /// public IStatisticsClient Statistics { get; private set; } + /// + /// Client for GitHub's Repository Commits API + /// + /// + /// See the Commits API documentation for more details + /// + public IRepositoryCommitsClient Commits { get; private set; } + /// /// Client for managing pull requests. /// @@ -426,23 +435,5 @@ public Task GetBranch(string owner, string repositoryName, string branch return ApiConnection.Get(ApiUrls.RepoBranch(owner, repositoryName, branchName)); } - - /// - /// Compare two references in a repository - /// - /// The owner of the repository - /// The name of the repository - /// The reference to use as the base commit - /// The reference to use as the head commit - /// - public Task Compare(string owner, string name, string @base, string head) - { - Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); - Ensure.ArgumentNotNullOrEmptyString(name, "repositoryName"); - Ensure.ArgumentNotNullOrEmptyString(@base, "base"); - Ensure.ArgumentNotNullOrEmptyString(head, "head"); - - return ApiConnection.Get(ApiUrls.RepoCompare(owner, name, @base, head)); - } } } diff --git a/Octokit/Clients/RepositoryCommitsClient.cs b/Octokit/Clients/RepositoryCommitsClient.cs new file mode 100644 index 0000000000..bc0a541a75 --- /dev/null +++ b/Octokit/Clients/RepositoryCommitsClient.cs @@ -0,0 +1,24 @@ +using System.Threading.Tasks; + +namespace Octokit +{ + public class RepositoryCommitsClient : IRepositoryCommitsClient + { + readonly IApiConnection _apiConnection; + + public RepositoryCommitsClient(IApiConnection apiConnection) + { + _apiConnection = apiConnection; + } + + public Task Compare(string owner, string name, string @base, string head) + { + Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); + Ensure.ArgumentNotNullOrEmptyString(name, "repositoryName"); + Ensure.ArgumentNotNullOrEmptyString(@base, "base"); + Ensure.ArgumentNotNullOrEmptyString(head, "head"); + + return _apiConnection.Get(ApiUrls.RepoCompare(owner, name, @base, head)); + } + } +} \ No newline at end of file diff --git a/Octokit/Octokit-Mono.csproj b/Octokit/Octokit-Mono.csproj index cd62c96ce3..6af736284f 100644 --- a/Octokit/Octokit-Mono.csproj +++ b/Octokit/Octokit-Mono.csproj @@ -311,6 +311,8 @@ + + \ No newline at end of file diff --git a/Octokit/Octokit-MonoAndroid.csproj b/Octokit/Octokit-MonoAndroid.csproj index c1630543c1..c29e354cc4 100644 --- a/Octokit/Octokit-MonoAndroid.csproj +++ b/Octokit/Octokit-MonoAndroid.csproj @@ -322,6 +322,8 @@ + + \ No newline at end of file diff --git a/Octokit/Octokit-Monotouch.csproj b/Octokit/Octokit-Monotouch.csproj index 603a097ff0..a4839dadfd 100644 --- a/Octokit/Octokit-Monotouch.csproj +++ b/Octokit/Octokit-Monotouch.csproj @@ -317,6 +317,8 @@ + + \ No newline at end of file diff --git a/Octokit/Octokit-netcore45.csproj b/Octokit/Octokit-netcore45.csproj index 14929305c2..5dc78b1133 100644 --- a/Octokit/Octokit-netcore45.csproj +++ b/Octokit/Octokit-netcore45.csproj @@ -309,6 +309,8 @@ + + diff --git a/Octokit/Octokit.csproj b/Octokit/Octokit.csproj index 076d7c9384..153347aa6b 100644 --- a/Octokit/Octokit.csproj +++ b/Octokit/Octokit.csproj @@ -53,10 +53,12 @@ Properties\SolutionInfo.cs + + From a1be7fefe7831b23daa4711129b5c7aeef502117 Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Sat, 8 Mar 2014 19:22:12 +1100 Subject: [PATCH 05/10] added proper reactive client --- .../Clients/IObservableRepositoriesClient.cs | 25 +++++++++-------- .../IObservableRepositoryCommitsClients.cs | 19 +++++++++++++ .../Clients/ObservableRepositoriesClient.cs | 9 ++++++ .../ObservableRepositoryCommitsClients.cs | 28 +++++++++++++++++++ Octokit.Reactive/Octokit.Reactive-Mono.csproj | 2 ++ .../Octokit.Reactive-MonoAndroid.csproj | 2 ++ .../Octokit.Reactive-Monotouch.csproj | 2 ++ Octokit.Reactive/Octokit.Reactive.csproj | 2 ++ 8 files changed, 78 insertions(+), 11 deletions(-) create mode 100644 Octokit.Reactive/Clients/IObservableRepositoryCommitsClients.cs create mode 100644 Octokit.Reactive/Clients/ObservableRepositoryCommitsClients.cs diff --git a/Octokit.Reactive/Clients/IObservableRepositoriesClient.cs b/Octokit.Reactive/Clients/IObservableRepositoriesClient.cs index 54ee223c60..a861d40486 100644 --- a/Octokit.Reactive/Clients/IObservableRepositoriesClient.cs +++ b/Octokit.Reactive/Clients/IObservableRepositoriesClient.cs @@ -213,17 +213,6 @@ public interface IObservableRepositoriesClient /// The updated IObservable Edit(string owner, string name, RepositoryUpdate update); - /// - /// Compare two references in a repository - /// - /// The owner of the repository - /// The name of the repository - /// The reference to use as the base commit - /// The reference to use as the head commit - /// - [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "base")] - IObservable Compare(string owner, string name, string @base, string @head); - /// /// A client for GitHub's Repo Collaborators. /// @@ -232,6 +221,20 @@ public interface IObservableRepositoriesClient /// IObservableRepoCollaboratorsClient RepoCollaborators { get; } + /// + /// Client for GitHub's Repository Commits API + /// + /// + /// See the Commits API documentation for more details + /// + IObservableRepositoryCommitsClient Commits { get; } + + /// + /// Client for managing pull requests. + /// + /// + /// See the Pull Requests API documentation for more details + /// IObservablePullRequestsClient PullRequest { get; } } } diff --git a/Octokit.Reactive/Clients/IObservableRepositoryCommitsClients.cs b/Octokit.Reactive/Clients/IObservableRepositoryCommitsClients.cs new file mode 100644 index 0000000000..bf8bfe5f0c --- /dev/null +++ b/Octokit.Reactive/Clients/IObservableRepositoryCommitsClients.cs @@ -0,0 +1,19 @@ +using System; +using System.Diagnostics.CodeAnalysis; + +namespace Octokit.Reactive +{ + public interface IObservableRepositoryCommitsClient + { + /// + /// Compare two references in a repository + /// + /// The owner of the repository + /// The name of the repository + /// The reference to use as the base commit + /// The reference to use as the head commit + /// + [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "base")] + IObservable Compare(string owner, string name, string @base, string @head); + } +} diff --git a/Octokit.Reactive/Clients/ObservableRepositoriesClient.cs b/Octokit.Reactive/Clients/ObservableRepositoriesClient.cs index d84588c23f..0a517a0fb2 100644 --- a/Octokit.Reactive/Clients/ObservableRepositoriesClient.cs +++ b/Octokit.Reactive/Clients/ObservableRepositoriesClient.cs @@ -25,6 +25,7 @@ public ObservableRepositoriesClient(IGitHubClient client) Statistics = new ObservableStatisticsClient(client); PullRequest = new ObservablePullRequestsClient(client); RepositoryComments = new ObservableRepositoryCommentsClient(client); + Commits = new ObservableRepositoryCommitsClient(client); } /// @@ -349,6 +350,14 @@ public IObservable Compare(string owner, string name, string @bas /// public IObservableRepoCollaboratorsClient RepoCollaborators { get; private set; } + /// + /// Client for GitHub's Repository Commits API + /// + /// + /// See the Commits API documentation for more details + /// + public IObservableRepositoryCommitsClient Commits { get; private set; } + /// /// Client for managing pull requests. /// diff --git a/Octokit.Reactive/Clients/ObservableRepositoryCommitsClients.cs b/Octokit.Reactive/Clients/ObservableRepositoryCommitsClients.cs new file mode 100644 index 0000000000..996e249134 --- /dev/null +++ b/Octokit.Reactive/Clients/ObservableRepositoryCommitsClients.cs @@ -0,0 +1,28 @@ +using System; +using System.Reactive.Threading.Tasks; + +namespace Octokit.Reactive +{ + public class ObservableRepositoryCommitsClient : IObservableRepositoryCommitsClient + { + readonly IGitHubClient _client; + + public ObservableRepositoryCommitsClient(IGitHubClient client) + { + _client = client; + } + + /// + /// Compare two references in a repository + /// + /// The owner of the repository + /// The name of the repository + /// The reference to use as the base commit + /// The reference to use as the head commit + /// + public IObservable Compare(string owner, string name, string @base, string head) + { + return _client.Repository.Commits.Compare(owner, name, @base, head).ToObservable(); + } + } +} \ No newline at end of file diff --git a/Octokit.Reactive/Octokit.Reactive-Mono.csproj b/Octokit.Reactive/Octokit.Reactive-Mono.csproj index 5dc511fd41..3882f838b4 100644 --- a/Octokit.Reactive/Octokit.Reactive-Mono.csproj +++ b/Octokit.Reactive/Octokit.Reactive-Mono.csproj @@ -141,6 +141,8 @@ + + diff --git a/Octokit.Reactive/Octokit.Reactive-MonoAndroid.csproj b/Octokit.Reactive/Octokit.Reactive-MonoAndroid.csproj index cd53c5a25c..acf6bfb085 100644 --- a/Octokit.Reactive/Octokit.Reactive-MonoAndroid.csproj +++ b/Octokit.Reactive/Octokit.Reactive-MonoAndroid.csproj @@ -150,6 +150,8 @@ + + diff --git a/Octokit.Reactive/Octokit.Reactive-Monotouch.csproj b/Octokit.Reactive/Octokit.Reactive-Monotouch.csproj index c8657d7fb0..5996e3ff11 100644 --- a/Octokit.Reactive/Octokit.Reactive-Monotouch.csproj +++ b/Octokit.Reactive/Octokit.Reactive-Monotouch.csproj @@ -145,6 +145,8 @@ + + diff --git a/Octokit.Reactive/Octokit.Reactive.csproj b/Octokit.Reactive/Octokit.Reactive.csproj index f08540c717..801fbd704e 100644 --- a/Octokit.Reactive/Octokit.Reactive.csproj +++ b/Octokit.Reactive/Octokit.Reactive.csproj @@ -73,6 +73,7 @@ Properties\SolutionInfo.cs + @@ -87,6 +88,7 @@ + From 9cc582a0341c58cc5410ba25522803256ef6e528 Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Fri, 14 Mar 2014 15:48:41 +1100 Subject: [PATCH 06/10] hey, here's some integration tests for ya --- .../Clients/RepositoryCommitsClientTests.cs | 139 ++++++++++++++++++ .../Octokit.Tests.Integration.csproj | 1 + 2 files changed, 140 insertions(+) create mode 100644 Octokit.Tests.Integration/Clients/RepositoryCommitsClientTests.cs diff --git a/Octokit.Tests.Integration/Clients/RepositoryCommitsClientTests.cs b/Octokit.Tests.Integration/Clients/RepositoryCommitsClientTests.cs new file mode 100644 index 0000000000..bab93aec4d --- /dev/null +++ b/Octokit.Tests.Integration/Clients/RepositoryCommitsClientTests.cs @@ -0,0 +1,139 @@ +using System; +using System.Collections.Generic; +using System.Reactive.Threading.Tasks; +using System.Threading.Tasks; +using Octokit; +using Octokit.Tests.Integration; +using Xunit; + +public class RepositoryCommitsClientTests : IDisposable +{ + readonly IGitHubClient _client; + IRepositoryCommitsClient _fixture; + Repository _repository; + + public RepositoryCommitsClientTests() + { + _client = new GitHubClient(new ProductHeaderValue("OctokitTests")) + { + Credentials = Helper.Credentials + }; + + _fixture = _client.Repository.Commits; + + var repoName = Helper.MakeNameWithTimestamp("source-repo"); + + _repository = _client.Repository.Create(new NewRepository { Name = repoName, AutoInit = true }).Result; + } + + [IntegrationTest] + public async Task CanCompareReferences() + { + await CreateTheWorld(); + + var result = await _fixture.Compare(Helper.UserName, _repository.Name, "master", "my-branch"); + + Assert.Equal(1, result.TotalCommits); + Assert.Equal(1, result.Commits.Count); + Assert.Equal(1, result.AheadBy); + Assert.Equal(0, result.BehindBy); + } + + [IntegrationTest] + public async Task CanCompareReferencesOtherWayRound() + { + await CreateTheWorld(); + + var result = await _fixture.Compare(Helper.UserName, _repository.Name, "my-branch", "master"); + + Assert.Equal(0, result.TotalCommits); + Assert.Equal(0, result.Commits.Count); + Assert.Equal(0, result.AheadBy); + Assert.Equal(1, result.BehindBy); + } + + [IntegrationTest] + public async Task ReturnsUrlsToResources() + { + await CreateTheWorld(); + + var result = await _fixture.Compare(Helper.UserName, _repository.Name, "my-branch", "master"); + + Assert.NotNull(result.DiffUrl); + Assert.NotNull(result.HtmlUrl); + Assert.NotNull(result.PatchUrl); + Assert.NotNull(result.PermalinkUrl); + } + + [IntegrationTest] + public async Task CanCompareUsingSha() + { + await CreateTheWorld(); + + var master = await _client.GitDatabase.Reference.Get(Helper.UserName, _repository.Name, "heads/master"); + var branch = await _client.GitDatabase.Reference.Get(Helper.UserName, _repository.Name, "heads/my-branch"); + + var result = await _fixture.Compare(Helper.UserName, _repository.Name, master.Object.Sha, branch.Object.Sha); + + Assert.Equal(1, result.Commits.Count); + Assert.Equal(1, result.AheadBy); + Assert.Equal(0, result.BehindBy); + } + + async Task CreateTheWorld() + { + var master = await _client.GitDatabase.Reference.Get(Helper.UserName, _repository.Name, "heads/master"); + + // create new commit for master branch + var newMasterTree = await CreateTree(new Dictionary { { "README.md", "Hello World!" } }); + var newMaster = await CreateCommit("baseline for pull request", newMasterTree.Sha, master.Object.Sha); + + // update master + await _client.GitDatabase.Reference.Update(Helper.UserName, _repository.Name, "heads/master", new ReferenceUpdate(newMaster.Sha)); + + // create new commit for feature branch + var featureBranchTree = await CreateTree(new Dictionary { { "README.md", "I am overwriting this blob with something new" } }); + var newFeature = await CreateCommit("this is the commit to merge into the pull request", featureBranchTree.Sha, newMaster.Sha); + + // create branch + await _client.GitDatabase.Reference.Create(Helper.UserName, _repository.Name, new NewReference("refs/heads/my-branch", newFeature.Sha)); + } + + async Task CreateTree(IDictionary treeContents) + { + var collection = new List(); + + foreach (var c in treeContents) + { + var baselineBlob = new NewBlob + { + Content = c.Value, + Encoding = EncodingType.Utf8 + }; + var baselineBlobResult = await _client.GitDatabase.Blob.Create(Helper.UserName, _repository.Name, baselineBlob); + + collection.Add(new NewTreeItem + { + Type = TreeType.Blob, + Mode = FileMode.File, + Path = c.Key, + Sha = baselineBlobResult.Sha + }); + } + + var newTree = new NewTree { Tree = collection }; + + return await _client.GitDatabase.Tree.Create(Helper.UserName, _repository.Name, newTree); + } + + async Task CreateCommit(string message, string sha, string parent) + { + var newCommit = new NewCommit(message, sha, parent); + return await _client.GitDatabase.Commit.Create(Helper.UserName, _repository.Name, newCommit); + } + + public void Dispose() + { + _client.Repository.Delete(_repository.Owner.Login, _repository.Name); + } +} diff --git a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj index 24eb70c148..3165b30719 100644 --- a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj +++ b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj @@ -71,6 +71,7 @@ + From 460232b522ab6a0b90a780306dfc8e68189df900 Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Fri, 14 Mar 2014 15:48:55 +1100 Subject: [PATCH 07/10] generate those xml-docs --- Octokit/Clients/RepositoryCommitsClient.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Octokit/Clients/RepositoryCommitsClient.cs b/Octokit/Clients/RepositoryCommitsClient.cs index bc0a541a75..76f5b05bba 100644 --- a/Octokit/Clients/RepositoryCommitsClient.cs +++ b/Octokit/Clients/RepositoryCommitsClient.cs @@ -1,4 +1,4 @@ -using System.Threading.Tasks; +using System.Threading.Tasks; namespace Octokit { @@ -11,6 +11,14 @@ public RepositoryCommitsClient(IApiConnection apiConnection) _apiConnection = apiConnection; } + /// + /// Compare two references in a repository + /// + /// The owner of the repository + /// The name of the repository + /// The reference to use as the base commit + /// The reference to use as the head commit + /// public Task Compare(string owner, string name, string @base, string head) { Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); From cb742eeb808b7574f7c631ef192100ca7089275a Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Wed, 19 Mar 2014 10:19:26 +1300 Subject: [PATCH 08/10] changed commit model over to enhanced type, updated usages --- Octokit/Models/Response/CompareResult.cs | 5 +++-- Octokit/Models/Response/GitHubCommit.cs | 19 +++++++++++++++++++ Octokit/Octokit-Mono.csproj | 1 + Octokit/Octokit-MonoAndroid.csproj | 1 + Octokit/Octokit-Monotouch.csproj | 1 + Octokit/Octokit-netcore45.csproj | 1 + Octokit/Octokit.csproj | 1 + 7 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 Octokit/Models/Response/GitHubCommit.cs diff --git a/Octokit/Models/Response/CompareResult.cs b/Octokit/Models/Response/CompareResult.cs index 874d0f19f1..9f7047a2f9 100644 --- a/Octokit/Models/Response/CompareResult.cs +++ b/Octokit/Models/Response/CompareResult.cs @@ -13,12 +13,13 @@ public class CompareResult public string PermalinkUrl { get; set; } public string DiffUrl { get; set; } public string PatchUrl { get; set; } - public Commit BaseCommit { get; set; } + public GitHubCommit BaseCommit { get; set; } + public GitHubCommit MergedBaseCommit { get; set; } public string Status { get; set; } public int AheadBy { get; set; } public int BehindBy { get; set; } public int TotalCommits { get; set; } - public IReadOnlyCollection Commits { get; set; } + public IReadOnlyCollection Commits { get; set; } internal string DebuggerDisplay { diff --git a/Octokit/Models/Response/GitHubCommit.cs b/Octokit/Models/Response/GitHubCommit.cs new file mode 100644 index 0000000000..f2a4815f21 --- /dev/null +++ b/Octokit/Models/Response/GitHubCommit.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using System.Diagnostics; + +namespace Octokit +{ + /// + /// An enhanced git commit containing links to additional resources + /// + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class GitHubCommit : GitReference + { + public Author Author { get; set; } + public string CommentsUrl { get; set; } + public Commit Commit { get; set; } + public Author Committer { get; set; } + public string HtmlUrl { get; set; } + public IReadOnlyList Parents { get; set; } + } +} \ No newline at end of file diff --git a/Octokit/Octokit-Mono.csproj b/Octokit/Octokit-Mono.csproj index 6af736284f..91610b8912 100644 --- a/Octokit/Octokit-Mono.csproj +++ b/Octokit/Octokit-Mono.csproj @@ -313,6 +313,7 @@ + \ No newline at end of file diff --git a/Octokit/Octokit-MonoAndroid.csproj b/Octokit/Octokit-MonoAndroid.csproj index c29e354cc4..bc1478fb46 100644 --- a/Octokit/Octokit-MonoAndroid.csproj +++ b/Octokit/Octokit-MonoAndroid.csproj @@ -324,6 +324,7 @@ + \ No newline at end of file diff --git a/Octokit/Octokit-Monotouch.csproj b/Octokit/Octokit-Monotouch.csproj index a4839dadfd..5574c29297 100644 --- a/Octokit/Octokit-Monotouch.csproj +++ b/Octokit/Octokit-Monotouch.csproj @@ -319,6 +319,7 @@ + \ No newline at end of file diff --git a/Octokit/Octokit-netcore45.csproj b/Octokit/Octokit-netcore45.csproj index 5dc78b1133..4c9069d2ce 100644 --- a/Octokit/Octokit-netcore45.csproj +++ b/Octokit/Octokit-netcore45.csproj @@ -311,6 +311,7 @@ + diff --git a/Octokit/Octokit.csproj b/Octokit/Octokit.csproj index 153347aa6b..1c0d93174a 100644 --- a/Octokit/Octokit.csproj +++ b/Octokit/Octokit.csproj @@ -66,6 +66,7 @@ + From db50ac6a5b735900dd44bf6876bbb477089387a7 Mon Sep 17 00:00:00 2001 From: Brendan's Test Account Date: Fri, 21 Mar 2014 11:12:10 +1300 Subject: [PATCH 09/10] add new components to Octokit.Portable --- Octokit/Octokit-Portable.csproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Octokit/Octokit-Portable.csproj b/Octokit/Octokit-Portable.csproj index 2ed7aa46ff..7c45307f6a 100644 --- a/Octokit/Octokit-Portable.csproj +++ b/Octokit/Octokit-Portable.csproj @@ -307,6 +307,10 @@ + + + + From ea9b0d27b0d46344bedbcd7d474e340ab8f0ad00 Mon Sep 17 00:00:00 2001 From: Brendan's Test Account Date: Fri, 21 Mar 2014 11:12:57 +1300 Subject: [PATCH 10/10] dat code review feedback --- .../Clients/ObservableRepositoryCommitsClients.cs | 2 +- Octokit/Clients/RepositoryCommitsClient.cs | 2 +- Octokit/Helpers/ApiUrls.cs | 11 ++++++++--- Octokit/Models/Response/Commit.cs | 4 +--- Octokit/Models/Response/GitHubCommit.cs | 2 +- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Octokit.Reactive/Clients/ObservableRepositoryCommitsClients.cs b/Octokit.Reactive/Clients/ObservableRepositoryCommitsClients.cs index 996e249134..d7eb1b091e 100644 --- a/Octokit.Reactive/Clients/ObservableRepositoryCommitsClients.cs +++ b/Octokit.Reactive/Clients/ObservableRepositoryCommitsClients.cs @@ -25,4 +25,4 @@ public IObservable Compare(string owner, string name, string @bas return _client.Repository.Commits.Compare(owner, name, @base, head).ToObservable(); } } -} \ No newline at end of file +} diff --git a/Octokit/Clients/RepositoryCommitsClient.cs b/Octokit/Clients/RepositoryCommitsClient.cs index 76f5b05bba..6d741604af 100644 --- a/Octokit/Clients/RepositoryCommitsClient.cs +++ b/Octokit/Clients/RepositoryCommitsClient.cs @@ -22,7 +22,7 @@ public RepositoryCommitsClient(IApiConnection apiConnection) public Task Compare(string owner, string name, string @base, string head) { Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); - Ensure.ArgumentNotNullOrEmptyString(name, "repositoryName"); + Ensure.ArgumentNotNullOrEmptyString(name, "name"); Ensure.ArgumentNotNullOrEmptyString(@base, "base"); Ensure.ArgumentNotNullOrEmptyString(head, "head"); diff --git a/Octokit/Helpers/ApiUrls.cs b/Octokit/Helpers/ApiUrls.cs index a39d09cdfd..2e3fe12929 100644 --- a/Octokit/Helpers/ApiUrls.cs +++ b/Octokit/Helpers/ApiUrls.cs @@ -1053,15 +1053,20 @@ public static Uri RepositoryTags(string owner, string name) /// Returns the for comparing two commits. /// /// The owner of the repository - /// The name of the repository + /// The name of the repository /// The base commit /// The head commit /// - public static Uri RepoCompare(string owner, string repositoryName, string @base, string head) + public static Uri RepoCompare(string owner, string name, string @base, string head) { + Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); + Ensure.ArgumentNotNullOrEmptyString(name, "name"); + Ensure.ArgumentNotNullOrEmptyString(@base, "base"); + Ensure.ArgumentNotNullOrEmptyString(head, "head"); + var encodedBase = @base.UriEncode(); var encodedHead = head.UriEncode(); - return "repos/{0}/{1}/compare/{2}...{3}".FormatUri(owner, repositoryName, encodedBase, encodedHead); + return "repos/{0}/{1}/compare/{2}...{3}".FormatUri(owner, name, encodedBase, encodedHead); } /// diff --git a/Octokit/Models/Response/Commit.cs b/Octokit/Models/Response/Commit.cs index c9b723a55d..097b2dc9e2 100644 --- a/Octokit/Models/Response/Commit.cs +++ b/Octokit/Models/Response/Commit.cs @@ -1,7 +1,5 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Diagnostics; -using System.Globalization; namespace Octokit { diff --git a/Octokit/Models/Response/GitHubCommit.cs b/Octokit/Models/Response/GitHubCommit.cs index f2a4815f21..315910396b 100644 --- a/Octokit/Models/Response/GitHubCommit.cs +++ b/Octokit/Models/Response/GitHubCommit.cs @@ -16,4 +16,4 @@ public class GitHubCommit : GitReference public string HtmlUrl { get; set; } public IReadOnlyList Parents { get; set; } } -} \ No newline at end of file +}