diff --git a/Octokit.Reactive/Clients/IObservableReleasesClient.cs b/Octokit.Reactive/Clients/IObservableReleasesClient.cs index ec56e379e4..b4a2b2a200 100644 --- a/Octokit.Reactive/Clients/IObservableReleasesClient.cs +++ b/Octokit.Reactive/Clients/IObservableReleasesClient.cs @@ -66,9 +66,20 @@ public interface IObservableReleasesClient /// The repository's name /// The id of the release /// Thrown when a general API error occurs. - [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", Justification = "Method makes a network request")] IObservable Get(string owner, string name, int id); + /// + /// Gets a single for the specified repository. + /// + /// + /// See the API documentation for more information. + /// + /// The repository's owner + /// The repository's name + /// The tag of the release + /// Thrown when a general API error occurs. + IObservable Get(string owner, string name, string tag); + /// /// Gets a single for the specified repository. /// @@ -78,9 +89,19 @@ public interface IObservableReleasesClient /// The Id of the repository /// The id of the release /// Thrown when a general API error occurs. - [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", Justification = "Method makes a network request")] IObservable Get(long repositoryId, int id); + /// + /// Gets a single for the specified repository. + /// + /// + /// See the API documentation for more information. + /// + /// The Id of the repository + /// The tag of the release + /// Thrown when a general API error occurs. + IObservable Get(long repositoryId, string tag); + /// /// Gets the latest for the specified repository. /// diff --git a/Octokit.Reactive/Clients/ObservableReleasesClient.cs b/Octokit.Reactive/Clients/ObservableReleasesClient.cs index 25d6abb3df..b9568e56dc 100644 --- a/Octokit.Reactive/Clients/ObservableReleasesClient.cs +++ b/Octokit.Reactive/Clients/ObservableReleasesClient.cs @@ -107,6 +107,25 @@ public IObservable Get(string owner, string name, int id) return _client.Get(owner, name, id).ToObservable(); } + /// + /// Gets a single for the specified repository. + /// + /// + /// See the API documentation for more information. + /// + /// The repository's owner + /// The repository's name + /// The tag of the release + /// Thrown when a general API error occurs. + public IObservable Get(string owner, string name, string tag) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + Ensure.ArgumentNotNullOrEmptyString(tag, nameof(tag)); + + return _client.Get(owner, name, tag).ToObservable(); + } + /// /// Gets a single for the specified repository. /// @@ -121,6 +140,22 @@ public IObservable Get(long repositoryId, int id) return _client.Get(repositoryId, id).ToObservable(); } + /// + /// Gets a single for the specified repository. + /// + /// + /// See the API documentation for more information. + /// + /// The Id of the repository + /// The tag of the release + /// Thrown when a general API error occurs. + public IObservable Get(long repositoryId, string tag) + { + Ensure.ArgumentNotNullOrEmptyString(tag, nameof(tag)); + + return _client.Get(repositoryId, tag).ToObservable(); + } + /// /// Gets the latest for the specified repository. /// diff --git a/Octokit.Tests.Integration/Clients/ReleasesClientTests.cs b/Octokit.Tests.Integration/Clients/ReleasesClientTests.cs index b06f4cfc10..176fd9245b 100644 --- a/Octokit.Tests.Integration/Clients/ReleasesClientTests.cs +++ b/Octokit.Tests.Integration/Clients/ReleasesClientTests.cs @@ -168,6 +168,50 @@ public void Dispose() } } + public class TheGetMethod + { + private readonly IReleasesClient _releaseClient; + private readonly IGitHubClient _client; + + public TheGetMethod() + { + _client = Helper.GetAuthenticatedClient(); + _releaseClient = _client.Repository.Release; + } + + [IntegrationTest] + public async Task ReturnsReleaseByTag() + { + var releaseByTag = await _releaseClient.Get("octokit", "octokit.net", "v0.28.0"); + + Assert.Equal(releaseByTag.Id, 8396883); + Assert.Equal(releaseByTag.Name, "v0.28 - Get to the Chopper!!!"); + Assert.Equal(releaseByTag.TagName, "v0.28.0"); + } + + [IntegrationTest] + public async Task ReturnsReleaseWithRepositoryIdByTag() + { + var releaseByTag = await _releaseClient.Get(7528679, "v0.28.0"); + + Assert.Equal(releaseByTag.Id, 8396883); + Assert.Equal(releaseByTag.Name, "v0.28 - Get to the Chopper!!!"); + Assert.Equal(releaseByTag.TagName, "v0.28.0"); + } + + [IntegrationTest] + public async Task ThrowsWhenTagNotFound() + { + await Assert.ThrowsAsync(() => _releaseClient.Get("octokit", "octokit.net", "0.0")); + } + + [IntegrationTest] + public async Task ThrowsWhenTagNotFoundWithRepositoryId() + { + await Assert.ThrowsAsync(() => _releaseClient.Get(7528679, "0.0")); + } + } + public class TheGetAllMethod { readonly IReleasesClient _releaseClient; diff --git a/Octokit.Tests.Integration/Reactive/ObservableReleaseClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableReleaseClientTests.cs index 337f2894d5..c706704b1a 100644 --- a/Octokit.Tests.Integration/Reactive/ObservableReleaseClientTests.cs +++ b/Octokit.Tests.Integration/Reactive/ObservableReleaseClientTests.cs @@ -84,5 +84,49 @@ public async Task ReturnsDistinctResultsBasedOnStartPage() Assert.NotEqual(firstPage[4].Id, secondPage[4].Id); } } + + public class TheGetMethod + { + readonly ObservableReleasesClient _releaseClient; + + public TheGetMethod() + { + var github = Helper.GetAuthenticatedClient(); + + _releaseClient = new ObservableReleasesClient(github); + } + + [IntegrationTest] + public async Task ReturnsReleaseByTag() + { + var releaseByTag = await _releaseClient.Get("octokit", "octokit.net", "v0.28.0"); + + Assert.Equal(releaseByTag.Id, 8396883); + Assert.Equal(releaseByTag.Name, "v0.28 - Get to the Chopper!!!"); + Assert.Equal(releaseByTag.TagName, "v0.28.0"); + } + + [IntegrationTest] + public async Task ReturnsReleaseWithRepositoryIdByTag() + { + var releaseByTag = await _releaseClient.Get(7528679, "v0.28.0"); + + Assert.Equal(releaseByTag.Id, 8396883); + Assert.Equal(releaseByTag.Name, "v0.28 - Get to the Chopper!!!"); + Assert.Equal(releaseByTag.TagName, "v0.28.0"); + } + + [IntegrationTest] + public async Task ThrowsWhenTagNotFound() + { + await Assert.ThrowsAsync(async () => await _releaseClient.Get("octokit", "octokit.net", "0.0")); + } + + [IntegrationTest] + public async Task ThrowsWhenTagNotFoundWithRepositoryId() + { + await Assert.ThrowsAsync(async () => await _releaseClient.Get(7528679, "0.0")); + } + } } } diff --git a/Octokit.Tests/Clients/ReleasesClientTests.cs b/Octokit.Tests/Clients/ReleasesClientTests.cs index 09a2c49ac0..db25679e88 100644 --- a/Octokit.Tests/Clients/ReleasesClientTests.cs +++ b/Octokit.Tests/Clients/ReleasesClientTests.cs @@ -123,6 +123,17 @@ public async Task RequestsTheCorrectUrl() connection.Received().Get(Arg.Is(u => u.ToString() == "repos/fake/repo/releases/1")); } + [Fact] + public async Task RequestsTheCorrectUrlByTag() + { + var connection = Substitute.For(); + var client = new ReleasesClient(connection); + + await client.Get("fake", "repo", "tag"); + + connection.Received().Get(Arg.Is(u => u.ToString() == "repos/fake/repo/releases/tags/tag")); + } + [Fact] public async Task RequestsTheCorrectUrlWithRepositoryId() { @@ -134,6 +145,17 @@ public async Task RequestsTheCorrectUrlWithRepositoryId() connection.Received().Get(Arg.Is(u => u.ToString() == "repositories/1/releases/1")); } + [Fact] + public async Task RequestsTheCorrectUrlWithRepositoryIdByTag() + { + var connection = Substitute.For(); + var client = new ReleasesClient(connection); + + await client.Get(1, "tag"); + + connection.Received().Get(Arg.Is(u => u.ToString() == "repositories/1/releases/tags/tag")); + } + [Fact] public async Task EnsuresNonNullArguments() { @@ -144,6 +166,16 @@ public async Task EnsuresNonNullArguments() await Assert.ThrowsAsync(() => releasesClient.Get("", "name", 1)); await Assert.ThrowsAsync(() => releasesClient.Get("owner", "", 1)); + + await Assert.ThrowsAsync(() => releasesClient.Get("owner", "name", null)); + await Assert.ThrowsAsync(() => releasesClient.Get("owner", "name", "")); + await Assert.ThrowsAsync(() => releasesClient.Get(null, "name", "tag")); + await Assert.ThrowsAsync(() => releasesClient.Get("", "name", "tag")); + await Assert.ThrowsAsync(() => releasesClient.Get("owner", null, "tag")); + await Assert.ThrowsAsync(() => releasesClient.Get("owner", "", "tag")); + + await Assert.ThrowsAsync(() => releasesClient.Get(1, null)); + await Assert.ThrowsAsync(() => releasesClient.Get(1, "")); } } diff --git a/Octokit.Tests/Reactive/ObservableReleasesClientTests.cs b/Octokit.Tests/Reactive/ObservableReleasesClientTests.cs index 7d85c5ae13..438bd1fe91 100644 --- a/Octokit.Tests/Reactive/ObservableReleasesClientTests.cs +++ b/Octokit.Tests/Reactive/ObservableReleasesClientTests.cs @@ -126,6 +126,28 @@ public void RequestsTheCorrectUrlWithRepositoryId() gitHubClient.Repository.Release.Received(1).Get(1, 1); } + [Fact] + public void RequestsTheCorrectUrlByTag() + { + var gitHubClient = Substitute.For(); + var client = new ObservableReleasesClient(gitHubClient); + + client.Get("fake", "repo", "tag"); + + gitHubClient.Repository.Release.Received(1).Get("fake", "repo", "tag"); + } + + [Fact] + public void RequestsTheCorrectUrlWithRepositoryIdByTag() + { + var gitHubClient = Substitute.For(); + var client = new ObservableReleasesClient(gitHubClient); + + client.Get(1, "tag"); + + gitHubClient.Repository.Release.Received(1).Get(1, "tag"); + } + [Fact] public void EnsuresNonNullArguments() { @@ -136,6 +158,13 @@ public void EnsuresNonNullArguments() Assert.Throws(() => releasesClient.Get("", "name", 1)); Assert.Throws(() => releasesClient.Get("owner", "", 1)); + + Assert.Throws(() => releasesClient.Get(null, "name", "tag")); + Assert.Throws(() => releasesClient.Get("", "name", "tag")); + Assert.Throws(() => releasesClient.Get("owner", null, "tag")); + Assert.Throws(() => releasesClient.Get("owner", "", "tag")); + Assert.Throws(() => releasesClient.Get("owner", "name", null)); + Assert.Throws(() => releasesClient.Get("owner", "name", "")); } } diff --git a/Octokit/Clients/IReleasesClient.cs b/Octokit/Clients/IReleasesClient.cs index 46293ecc66..56a700a23c 100644 --- a/Octokit/Clients/IReleasesClient.cs +++ b/Octokit/Clients/IReleasesClient.cs @@ -66,9 +66,20 @@ public interface IReleasesClient /// The repository's name /// The id of the release /// Thrown when a general API error occurs. - [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", Justification = "Method makes a network request")] Task Get(string owner, string name, int id); + /// + /// Gets a single for the specified repository. + /// + /// + /// See the API documentation for more information. + /// + /// The repository's owner + /// The repository's name + /// The tag of the release + /// Thrown when a general API error occurs. + Task Get(string owner, string name, string tag); + /// /// Gets a single for the specified repository. /// @@ -78,9 +89,19 @@ public interface IReleasesClient /// The Id of the repository /// The id of the release /// Thrown when a general API error occurs. - [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", Justification = "Method makes a network request")] Task Get(long repositoryId, int id); + /// + /// Gets a single for the specified repository. + /// + /// + /// See the API documentation for more information. + /// + /// The Id of the repository + /// The tag of the release + /// Thrown when a general API error occurs. + Task Get(long repositoryId, string tag); + /// /// Gets the latest for the specified repository. /// diff --git a/Octokit/Clients/ReleasesClient.cs b/Octokit/Clients/ReleasesClient.cs index 804df0222e..7dd95ebafb 100644 --- a/Octokit/Clients/ReleasesClient.cs +++ b/Octokit/Clients/ReleasesClient.cs @@ -105,6 +105,26 @@ public Task Get(string owner, string name, int id) return ApiConnection.Get(endpoint); } + /// + /// Gets a single for the specified repository. + /// + /// + /// See the API documentation for more information. + /// + /// The repository's owner + /// The repository's name + /// The tag of the release + /// Thrown when a general API error occurs. + public Task Get(string owner, string name, string tag) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + Ensure.ArgumentNotNullOrEmptyString(tag, nameof(tag)); + + var endpoint = ApiUrls.Releases(owner, name, tag); + return ApiConnection.Get(endpoint); + } + /// /// Gets a single for the specified repository. /// @@ -120,6 +140,23 @@ public Task Get(long repositoryId, int id) return ApiConnection.Get(endpoint); } + /// + /// Gets a single for the specified repository. + /// + /// + /// See the API documentation for more information. + /// + /// The Id of the repository + /// The tag of the release + /// Thrown when a general API error occurs. + public Task Get(long repositoryId, string tag) + { + Ensure.ArgumentNotNullOrEmptyString(tag, nameof(tag)); + + var endpoint = ApiUrls.Releases(repositoryId, tag); + return ApiConnection.Get(endpoint); + } + /// /// Gets the latest for the specified repository. /// diff --git a/Octokit/Helpers/ApiUrls.cs b/Octokit/Helpers/ApiUrls.cs index c49ed88b75..4f8e949a90 100644 --- a/Octokit/Helpers/ApiUrls.cs +++ b/Octokit/Helpers/ApiUrls.cs @@ -215,6 +215,18 @@ public static Uri Releases(string owner, string name, int id) return "repos/{0}/{1}/releases/{2}".FormatUri(owner, name, id); } + /// + /// Returns the that returns a single release for the specified repository + /// + /// The owner of the repository + /// The name of the repository + /// The tag of the release + /// + public static Uri Releases(string owner, string name, string tag) + { + return "repos/{0}/{1}/releases/tags/{2}".FormatUri(owner, name, tag); + } + /// /// Returns the that returns the latest release for the specified repository /// @@ -3082,6 +3094,17 @@ public static Uri Releases(long repositoryId, int id) return "repositories/{0}/releases/{1}".FormatUri(repositoryId, id); } + /// + /// Returns the that returns a single release for the specified repository + /// + /// The Id of the repository + /// The tag of the release + /// The that returns a single release for the specified repository + public static Uri Releases(long repositoryId, string tag) + { + return "repositories/{0}/releases/tags/{1}".FormatUri(repositoryId, tag); + } + /// /// Returns the for a repository branch. ///