mirror of
https://github.com/zoriya/octokit.net.git
synced 2026-06-05 11:40:42 +00:00
Merge pull request #862 from octokit/haacked/836-handle-empty-content
Handle empty content better
This commit is contained in:
@@ -71,7 +71,8 @@ namespace Octokit.Tests.Conventions
|
||||
.Where(x => x.Name.StartsWith("Get"));
|
||||
|
||||
var invalidMethods = methodsThatCanPaginate
|
||||
.Where(x => !x.Name.StartsWith("GetAll"));
|
||||
.Where(x => !x.Name.StartsWith("GetAll"))
|
||||
.ToList();
|
||||
|
||||
if (invalidMethods.Any())
|
||||
{
|
||||
@@ -81,7 +82,12 @@ namespace Octokit.Tests.Conventions
|
||||
|
||||
public static IEnumerable<object[]> GetClientInterfaces()
|
||||
{
|
||||
return typeof(IEventsClient).Assembly.ExportedTypes.Where(TypeExtensions.IsClientInterface).Select(type => new[] { type });
|
||||
return typeof(IEventsClient)
|
||||
.Assembly
|
||||
.ExportedTypes
|
||||
.Where(TypeExtensions.IsClientInterface)
|
||||
.Where(t => t != typeof(IStatisticsClient)) // This convention doesn't apply to this one type.
|
||||
.Select(type => new[] { type });
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> ModelTypes
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reactive;
|
||||
using System.Reflection;
|
||||
using Octokit.Tests.Helpers;
|
||||
using Xunit;
|
||||
using Xunit.Extensions;
|
||||
|
||||
namespace Octokit.Tests.Conventions
|
||||
{
|
||||
@@ -22,13 +20,13 @@ namespace Octokit.Tests.Conventions
|
||||
var mainNames = Array.ConvertAll(mainMethods, m => m.Name);
|
||||
var observableNames = Array.ConvertAll(observableMethods, m => m.Name);
|
||||
|
||||
var methodsMissingOnReactiveClient = mainNames.Except(observableNames);
|
||||
var methodsMissingOnReactiveClient = mainNames.Except(observableNames).ToList();
|
||||
if (methodsMissingOnReactiveClient.Any())
|
||||
{
|
||||
throw new InterfaceMissingMethodsException(observableClient, methodsMissingOnReactiveClient);
|
||||
}
|
||||
|
||||
var additionalMethodsOnReactiveClient = observableNames.Except(mainNames);
|
||||
var additionalMethodsOnReactiveClient = observableNames.Except(mainNames).ToList();
|
||||
if (additionalMethodsOnReactiveClient.Any())
|
||||
{
|
||||
throw new InterfaceHasAdditionalMethodsException(observableClient, additionalMethodsOnReactiveClient);
|
||||
@@ -122,7 +120,12 @@ namespace Octokit.Tests.Conventions
|
||||
|
||||
public static IEnumerable<object[]> GetClientInterfaces()
|
||||
{
|
||||
return typeof(IEventsClient).Assembly.ExportedTypes.Where(TypeExtensions.IsClientInterface).Select(type => new[] { type });
|
||||
return typeof(IEventsClient)
|
||||
.Assembly
|
||||
.ExportedTypes
|
||||
.Where(TypeExtensions.IsClientInterface)
|
||||
.Where(t => t != typeof(IStatisticsClient)) // This convention doesn't apply to this one type.
|
||||
.Select(type => new[] { type });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Linq;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
@@ -18,21 +17,31 @@ namespace Octokit.Tests.Integration.Clients
|
||||
}
|
||||
|
||||
[IntegrationTest]
|
||||
public async Task CanCreateAndRetrieveCommit()
|
||||
public async Task CanCreateAndRetrieveContributors()
|
||||
{
|
||||
var repository = await CreateRepository();
|
||||
await CommitToRepository(repository);
|
||||
var contributors = await _client.Repository.Statistics.GetContributors(repository.Owner, repository.Name);
|
||||
|
||||
Assert.NotNull(contributors);
|
||||
Assert.True(contributors.Count() == 1);
|
||||
Assert.Equal(1, contributors.Count);
|
||||
|
||||
var soleContributor = contributors.First();
|
||||
Assert.NotNull(soleContributor.Author);
|
||||
Assert.True(soleContributor.Author.Login == repository.Owner);
|
||||
|
||||
Assert.True(soleContributor.Weeks.Count() == 1);
|
||||
Assert.True(soleContributor.Total == 1);
|
||||
Assert.Equal(1, soleContributor.Weeks.Count);
|
||||
Assert.Equal(1, soleContributor.Total);
|
||||
}
|
||||
|
||||
[IntegrationTest]
|
||||
public async Task CanCreateAndRetrieveEmptyContributors()
|
||||
{
|
||||
var repository = await CreateRepository(autoInit: false);
|
||||
var contributors = await _client.Repository.Statistics.GetContributors(repository.Owner, repository.Name);
|
||||
|
||||
Assert.NotNull(contributors);
|
||||
Assert.Empty(contributors);
|
||||
}
|
||||
|
||||
[IntegrationTest]
|
||||
@@ -42,10 +51,10 @@ namespace Octokit.Tests.Integration.Clients
|
||||
await CommitToRepository(repository);
|
||||
var commitActivities = await _client.Repository.Statistics.GetCommitActivity(repository.Owner, repository.Name);
|
||||
Assert.NotNull(commitActivities);
|
||||
Assert.True(commitActivities.Activity.Count() == 52);
|
||||
Assert.Equal(52, commitActivities.Activity.Count);
|
||||
|
||||
var thisWeek = commitActivities.Activity.Last();
|
||||
Assert.True(thisWeek.Total == 1);
|
||||
Assert.Equal(1, thisWeek.Total);
|
||||
Assert.NotNull(thisWeek.Days);
|
||||
}
|
||||
|
||||
@@ -65,9 +74,7 @@ namespace Octokit.Tests.Integration.Clients
|
||||
var repository = await CreateRepository();
|
||||
await CommitToRepository(repository);
|
||||
var weeklyCommitCounts = await _client.Repository.Statistics.GetParticipation(repository.Owner, repository.Name);
|
||||
Assert.NotNull(weeklyCommitCounts);
|
||||
Assert.NotNull(weeklyCommitCounts.All);
|
||||
Assert.NotNull(weeklyCommitCounts.Owner);
|
||||
Assert.Equal(52, weeklyCommitCounts.All.Count);
|
||||
}
|
||||
|
||||
[IntegrationTest]
|
||||
@@ -80,10 +87,10 @@ namespace Octokit.Tests.Integration.Clients
|
||||
Assert.NotNull(punchCard.PunchPoints);
|
||||
}
|
||||
|
||||
async Task<RepositorySummary> CreateRepository()
|
||||
async Task<RepositorySummary> CreateRepository(bool autoInit = true)
|
||||
{
|
||||
var repoName = Helper.MakeNameWithTimestamp("public-repo");
|
||||
var repository = await _client.Repository.Create(new NewRepository(repoName) { AutoInit = true });
|
||||
var repository = await _client.Repository.Create(new NewRepository(repoName) { AutoInit = autoInit });
|
||||
return new RepositorySummary
|
||||
{
|
||||
Owner = repository.Owner.Login,
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Threading.Tasks;
|
||||
using NSubstitute;
|
||||
using Octokit.Tests.Helpers;
|
||||
using Octokit.Helpers;
|
||||
using Xunit;
|
||||
|
||||
namespace Octokit.Tests.Clients
|
||||
@@ -21,16 +22,18 @@ namespace Octokit.Tests.Clients
|
||||
public class TheGetContributorsMethod
|
||||
{
|
||||
[Fact]
|
||||
public void RequestsCorrectUrl()
|
||||
public async Task RetrievesContributorsForCorrectUrl()
|
||||
{
|
||||
var expectedEndPoint = new Uri("/repos/username/repositoryName/stats/contributors", UriKind.Relative);
|
||||
|
||||
var client = Substitute.For<IApiConnection>();
|
||||
IReadOnlyList<Contributor> contributors = new ReadOnlyCollection<Contributor>(new[] { new Contributor() });
|
||||
client.GetQueuedOperation<Contributor>(expectedEndPoint, Args.CancellationToken)
|
||||
.Returns(Task.FromResult(contributors));
|
||||
var statisticsClient = new StatisticsClient(client);
|
||||
|
||||
statisticsClient.GetContributors("username","repositoryName");
|
||||
var result = await statisticsClient.GetContributors("username","repositoryName");
|
||||
|
||||
client.Received().GetQueuedOperation<IEnumerable<Contributor>>(expectedEndPoint,Args.CancellationToken);
|
||||
Assert.Equal(1, result.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -51,16 +54,24 @@ namespace Octokit.Tests.Clients
|
||||
public class TheGetCommitActivityForTheLastYearMethod
|
||||
{
|
||||
[Fact]
|
||||
public void RequestsCorrectUrl()
|
||||
public async Task RequestsCorrectUrl()
|
||||
{
|
||||
var expectedEndPoint = new Uri("/repos/username/repositoryName/stats/commit_activity", UriKind.Relative);
|
||||
|
||||
var data = new WeeklyCommitActivity(new[] { 1, 2 }, 100, 42);
|
||||
IReadOnlyList<WeeklyCommitActivity> response = new ReadOnlyCollection<WeeklyCommitActivity>(new[] { data });
|
||||
var client = Substitute.For<IApiConnection>();
|
||||
client.GetQueuedOperation<WeeklyCommitActivity>(expectedEndPoint, Args.CancellationToken)
|
||||
.Returns(Task.FromResult(response));
|
||||
var statisticsClient = new StatisticsClient(client);
|
||||
|
||||
statisticsClient.GetCommitActivity("username", "repositoryName");
|
||||
var result = await statisticsClient.GetCommitActivity("username", "repositoryName");
|
||||
|
||||
client.Received().GetQueuedOperation<IReadOnlyList<WeeklyCommitActivity>>(expectedEndPoint, Args.CancellationToken);
|
||||
Assert.Equal(2, result.Activity[0].Days.Count);
|
||||
Assert.Equal(1, result.Activity[0].Days[0]);
|
||||
Assert.Equal(2, result.Activity[0].Days[1]);
|
||||
Assert.Equal(100, result.Activity[0].Total);
|
||||
Assert.Equal(42, result.Activity[0].Week);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -81,16 +92,31 @@ namespace Octokit.Tests.Clients
|
||||
public class TheGetAdditionsAndDeletionsPerWeekMethod
|
||||
{
|
||||
[Fact]
|
||||
public void RequestsCorrectUrl()
|
||||
public async Task RequestsCorrectUrl()
|
||||
{
|
||||
var expectedEndPoint = new Uri("/repos/username/repositoryName/stats/code_frequency", UriKind.Relative);
|
||||
|
||||
long firstTimestamp = 159670861;
|
||||
long secondTimestamp = 0;
|
||||
IReadOnlyList<long[]> data = new ReadOnlyCollection<long[]>(new[]
|
||||
{
|
||||
new[] { firstTimestamp, 10, 52 },
|
||||
new[] { secondTimestamp, 0, 9 }
|
||||
});
|
||||
var client = Substitute.For<IApiConnection>();
|
||||
client.GetQueuedOperation<long[]>(expectedEndPoint, Args.CancellationToken)
|
||||
.Returns(Task.FromResult(data));
|
||||
var statisticsClient = new StatisticsClient(client);
|
||||
|
||||
statisticsClient.GetCodeFrequency("username", "repositoryName");
|
||||
var codeFrequency = await statisticsClient.GetCodeFrequency("username", "repositoryName");
|
||||
|
||||
client.Received().GetQueuedOperation<IEnumerable<long[]>>(expectedEndPoint, Args.CancellationToken);
|
||||
Assert.Equal(2, codeFrequency.AdditionsAndDeletionsByWeek.Count);
|
||||
Assert.Equal(firstTimestamp.FromUnixTime(), codeFrequency.AdditionsAndDeletionsByWeek[0].Timestamp);
|
||||
Assert.Equal(10, codeFrequency.AdditionsAndDeletionsByWeek[0].Additions);
|
||||
Assert.Equal(52, codeFrequency.AdditionsAndDeletionsByWeek[0].Deletions);
|
||||
Assert.Equal(secondTimestamp.FromUnixTime(), codeFrequency.AdditionsAndDeletionsByWeek[1].Timestamp);
|
||||
Assert.Equal(0, codeFrequency.AdditionsAndDeletionsByWeek[1].Additions);
|
||||
Assert.Equal(9, codeFrequency.AdditionsAndDeletionsByWeek[1].Deletions);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -141,16 +167,22 @@ namespace Octokit.Tests.Clients
|
||||
public class TheGetHourlyCommitCountsMethod
|
||||
{
|
||||
[Fact]
|
||||
public void RequestsCorrectUrl()
|
||||
public async Task RetrievesPunchCard()
|
||||
{
|
||||
var expectedEndPoint = new Uri("/repos/username/repositoryName/stats/punch_card", UriKind.Relative);
|
||||
|
||||
var client = Substitute.For<IApiConnection>();
|
||||
IReadOnlyList<int[]> data = new ReadOnlyCollection<int[]>(new[] { new[] { 2, 8, 42 } });
|
||||
client.GetQueuedOperation<int[]>(expectedEndPoint, Args.CancellationToken)
|
||||
.Returns(Task.FromResult(data));
|
||||
var statisticsClient = new StatisticsClient(client);
|
||||
|
||||
statisticsClient.GetPunchCard("username", "repositoryName");
|
||||
var result = await statisticsClient.GetPunchCard("username", "repositoryName");
|
||||
|
||||
client.Received().GetQueuedOperation<IEnumerable<int[]>>(expectedEndPoint, Args.CancellationToken);
|
||||
Assert.Equal(1, result.PunchPoints.Count);
|
||||
Assert.Equal(DayOfWeek.Tuesday, result.PunchPoints[0].DayOfWeek);
|
||||
Assert.Equal(8, result.PunchPoints[0].HourOfTheDay);
|
||||
Assert.Equal(42, result.PunchPoints[0].CommitCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -168,4 +200,4 @@ namespace Octokit.Tests.Clients
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using Octokit.Helpers;
|
||||
using Xunit;
|
||||
|
||||
public class UnixTimestampExtensionsTests
|
||||
{
|
||||
public class TheToUnixTimeMethod
|
||||
{
|
||||
[Fact]
|
||||
public void ReturnsUnixEpochCorrectly()
|
||||
{
|
||||
var epoch = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
|
||||
Assert.Equal(0, epoch.ToUnixTime());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReturnsRandomDateCorrectly()
|
||||
{
|
||||
var epoch = new DateTimeOffset(1975, 1, 23, 1, 1, 1, TimeSpan.Zero);
|
||||
Assert.Equal(159670861, epoch.ToUnixTime());
|
||||
}
|
||||
}
|
||||
|
||||
public class TheFromUnixTimeMethod
|
||||
{
|
||||
[Fact]
|
||||
public void ReturnsDateFromUnixEpochCorrectly()
|
||||
{
|
||||
var epoch = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
|
||||
|
||||
var result = ((long)0).FromUnixTime();
|
||||
|
||||
Assert.Equal(epoch, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReturnsDateFromRandomTimeCorrectly()
|
||||
{
|
||||
var expected = new DateTimeOffset(1975, 1, 23, 1, 1, 2, TimeSpan.Zero);
|
||||
|
||||
var result = ((long)159670862).FromUnixTime();
|
||||
|
||||
Assert.Equal(expected, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using NSubstitute;
|
||||
using Octokit.Internal;
|
||||
using Octokit.Tests.Helpers;
|
||||
using Xunit;
|
||||
|
||||
namespace Octokit.Tests.Http
|
||||
@@ -315,22 +314,6 @@ namespace Octokit.Tests.Http
|
||||
|
||||
public class TheGetQueuedOperationMethod
|
||||
{
|
||||
[Fact]
|
||||
public async Task MakesGetRequest()
|
||||
{
|
||||
var queuedOperationUrl = new Uri("anything", UriKind.Relative);
|
||||
|
||||
const HttpStatusCode statusCode = HttpStatusCode.OK;
|
||||
IApiResponse<object> response = new ApiResponse<object>(new Response(statusCode, null, new Dictionary<string, string>(), "application/json"), new object());
|
||||
var connection = Substitute.For<IConnection>();
|
||||
connection.GetResponse<object>(queuedOperationUrl,Args.CancellationToken).Returns(Task.FromResult(response));
|
||||
var apiConnection = new ApiConnection(connection);
|
||||
|
||||
await apiConnection.GetQueuedOperation<object>(queuedOperationUrl,CancellationToken.None);
|
||||
|
||||
connection.Received().GetResponse<object>(queuedOperationUrl, Args.CancellationToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task WhenGetReturnsNotOkOrAcceptedApiExceptionIsThrown()
|
||||
{
|
||||
@@ -350,15 +333,36 @@ namespace Octokit.Tests.Http
|
||||
{
|
||||
var queuedOperationUrl = new Uri("anything", UriKind.Relative);
|
||||
|
||||
var result = new object();
|
||||
var result = new[] { new object() };
|
||||
const HttpStatusCode statusCode = HttpStatusCode.OK;
|
||||
IApiResponse<object> response = new ApiResponse<object>(new Response(statusCode, null, new Dictionary<string, string>(), "application/json"), result);
|
||||
var httpResponse = new Response(statusCode, null, new Dictionary<string, string>(), "application/json");
|
||||
IApiResponse<IReadOnlyList<object>> response = new ApiResponse<IReadOnlyList<object>>(httpResponse, result);
|
||||
var connection = Substitute.For<IConnection>();
|
||||
connection.GetResponse<object>(queuedOperationUrl, Args.CancellationToken).Returns(Task.FromResult(response));
|
||||
connection.GetResponse<IReadOnlyList<object>>(queuedOperationUrl, Args.CancellationToken)
|
||||
.Returns(Task.FromResult(response));
|
||||
var apiConnection = new ApiConnection(connection);
|
||||
|
||||
var actualResult = await apiConnection.GetQueuedOperation<object>(queuedOperationUrl, Args.CancellationToken);
|
||||
Assert.Same(actualResult,result);
|
||||
Assert.Same(actualResult, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task WhenGetReturnsNoContentThenReturnsEmptyCollection()
|
||||
{
|
||||
var queuedOperationUrl = new Uri("anything", UriKind.Relative);
|
||||
|
||||
var result = new [] { new object() };
|
||||
const HttpStatusCode statusCode = HttpStatusCode.NoContent;
|
||||
var httpResponse = new Response(statusCode, null, new Dictionary<string, string>(), "application/json");
|
||||
IApiResponse<IReadOnlyList<object>> response = new ApiResponse<IReadOnlyList<object>>(
|
||||
httpResponse, result);
|
||||
var connection = Substitute.For<IConnection>();
|
||||
connection.GetResponse<IReadOnlyList<object>>(queuedOperationUrl, Args.CancellationToken)
|
||||
.Returns(Task.FromResult(response));
|
||||
var apiConnection = new ApiConnection(connection);
|
||||
|
||||
var actualResult = await apiConnection.GetQueuedOperation<object>(queuedOperationUrl, Args.CancellationToken);
|
||||
Assert.Empty(actualResult);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -366,11 +370,13 @@ namespace Octokit.Tests.Http
|
||||
{
|
||||
var queuedOperationUrl = new Uri("anything", UriKind.Relative);
|
||||
|
||||
var result = new object();
|
||||
IApiResponse<object> firstResponse = new ApiResponse<object>(new Response(HttpStatusCode.Accepted, null, new Dictionary<string, string>(), "application/json"), result);
|
||||
IApiResponse<object> completedResponse = new ApiResponse<object>(new Response(HttpStatusCode.OK, null, new Dictionary<string, string>(), "application/json"), result);
|
||||
var result = new [] { new object() };
|
||||
IApiResponse<IReadOnlyList<object>> firstResponse = new ApiResponse<IReadOnlyList<object>>(
|
||||
new Response(HttpStatusCode.Accepted, null, new Dictionary<string, string>(), "application/json"), result);
|
||||
IApiResponse<IReadOnlyList<object>> completedResponse = new ApiResponse<IReadOnlyList<object>>(
|
||||
new Response(HttpStatusCode.OK, null, new Dictionary<string, string>(), "application/json"), result);
|
||||
var connection = Substitute.For<IConnection>();
|
||||
connection.GetResponse<object>(queuedOperationUrl, Args.CancellationToken)
|
||||
connection.GetResponse<IReadOnlyList<object>>(queuedOperationUrl, Args.CancellationToken)
|
||||
.Returns(x => Task.FromResult(firstResponse),
|
||||
x => Task.FromResult(firstResponse),
|
||||
x => Task.FromResult(completedResponse));
|
||||
@@ -379,17 +385,19 @@ namespace Octokit.Tests.Http
|
||||
|
||||
await apiConnection.GetQueuedOperation<object>(queuedOperationUrl, CancellationToken.None);
|
||||
|
||||
connection.Received(3).GetResponse<object>(queuedOperationUrl, Args.CancellationToken);
|
||||
connection.Received(3).GetResponse<IReadOnlyList<object>>(queuedOperationUrl, Args.CancellationToken);
|
||||
}
|
||||
|
||||
public async Task CanCancelQueuedOperation()
|
||||
{
|
||||
var queuedOperationUrl = new Uri("anything", UriKind.Relative);
|
||||
|
||||
var result = new object();
|
||||
IApiResponse<object> accepted = new ApiResponse<object>(new Response(HttpStatusCode.Accepted, null, new Dictionary<string, string>(), "application/json"), result);
|
||||
var result = new [] { new object() };
|
||||
IApiResponse<IReadOnlyList<object>> accepted = new ApiResponse<IReadOnlyList<object>>(
|
||||
new Response(HttpStatusCode.Accepted, null, new Dictionary<string, string>(), "application/json"), result);
|
||||
var connection = Substitute.For<IConnection>();
|
||||
connection.GetResponse<object>(queuedOperationUrl, Args.CancellationToken).Returns(x => Task.FromResult(accepted));
|
||||
connection.GetResponse<IReadOnlyList<object>>(queuedOperationUrl, Args.CancellationToken)
|
||||
.Returns(x => Task.FromResult(accepted));
|
||||
|
||||
var apiConnection = new ApiConnection(connection);
|
||||
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
<Compile Include="Exceptions\TwoFactorRequiredExceptionTests.cs" />
|
||||
<Compile Include="Helpers\NSubstituteExtensions.cs" />
|
||||
<Compile Include="Helpers\ReflectionExtensions.cs" />
|
||||
<Compile Include="Helpers\UnixTimestampExtensionsTests.cs" />
|
||||
<Compile Include="Helpers\UriExtensionsTests.cs" />
|
||||
<Compile Include="Http\ApiConnectionTests.cs" />
|
||||
<Compile Include="Clients\AuthorizationsClientTests.cs" />
|
||||
|
||||
@@ -107,6 +107,7 @@
|
||||
<Compile Include="Exceptions\TwoFactorRequiredExceptionTests.cs" />
|
||||
<Compile Include="Helpers\NSubstituteExtensions.cs" />
|
||||
<Compile Include="Helpers\ReflectionExtensions.cs" />
|
||||
<Compile Include="Helpers\UnixTimestampExtensionsTests.cs" />
|
||||
<Compile Include="Helpers\UriExtensionsTests.cs" />
|
||||
<Compile Include="Http\ApiConnectionTests.cs" />
|
||||
<Compile Include="Clients\AuthorizationsClientTests.cs" />
|
||||
|
||||
@@ -123,6 +123,7 @@
|
||||
<Compile Include="Exceptions\TwoFactorRequiredExceptionTests.cs" />
|
||||
<Compile Include="Helpers\NSubstituteExtensions.cs" />
|
||||
<Compile Include="Helpers\ReflectionExtensions.cs" />
|
||||
<Compile Include="Helpers\UnixTimestampExtensionsTests.cs" />
|
||||
<Compile Include="Helpers\UriExtensionsTests.cs" />
|
||||
<Compile Include="Http\ApiConnectionTests.cs" />
|
||||
<Compile Include="Clients\AuthorizationsClientTests.cs" />
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Octokit
|
||||
/// <param name="owner">The owner of the repository</param>
|
||||
/// <param name="repositoryName">The name of the repository</param>
|
||||
/// <returns>A list of <see cref="Contributor"/></returns>
|
||||
Task<IEnumerable<Contributor>> GetContributors(string owner, string repositoryName);
|
||||
Task<IReadOnlyList<Contributor>> GetContributors(string owner, string repositoryName);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of <see cref="Contributor"/> for the given repository
|
||||
@@ -27,7 +27,7 @@ namespace Octokit
|
||||
/// <param name="repositoryName">The name of the repository</param>
|
||||
/// <param name="cancellationToken">A token used to cancel this potentially long running request</param>
|
||||
/// <returns>A list of <see cref="Contributor"/></returns>
|
||||
Task<IEnumerable<Contributor>> GetContributors(string owner, string repositoryName, CancellationToken cancellationToken);
|
||||
Task<IReadOnlyList<Contributor>> GetContributors(string owner, string repositoryName, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the last year of commit activity grouped by week.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -26,7 +27,7 @@ namespace Octokit
|
||||
/// <param name="owner">The owner of the repository</param>
|
||||
/// <param name="repositoryName">The name of the repository</param>
|
||||
/// <returns>A list of <see cref="Contributor"/></returns>
|
||||
public Task<IEnumerable<Contributor>> GetContributors(string owner, string repositoryName)
|
||||
public Task<IReadOnlyList<Contributor>> GetContributors(string owner, string repositoryName)
|
||||
{
|
||||
return GetContributors(owner, repositoryName, CancellationToken.None);
|
||||
}
|
||||
@@ -38,13 +39,13 @@ namespace Octokit
|
||||
/// <param name="repositoryName">The name of the repository</param>
|
||||
/// <param name="cancellationToken">A token used to cancel this potentially long running request</param>
|
||||
/// <returns>A list of <see cref="Contributor"/></returns>
|
||||
public async Task<IEnumerable<Contributor>> GetContributors(string owner, string repositoryName, CancellationToken cancellationToken)
|
||||
public async Task<IReadOnlyList<Contributor>> GetContributors(string owner, string repositoryName, CancellationToken cancellationToken)
|
||||
{
|
||||
Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
|
||||
Ensure.ArgumentNotNullOrEmptyString(repositoryName, "repositoryName");
|
||||
|
||||
var endpoint = "/repos/{0}/{1}/stats/contributors".FormatUri(owner, repositoryName);
|
||||
return await ApiConnection.GetQueuedOperation<IEnumerable<Contributor>>(endpoint, cancellationToken);
|
||||
return await ApiConnection.GetQueuedOperation<Contributor>(endpoint, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -71,7 +72,7 @@ namespace Octokit
|
||||
Ensure.ArgumentNotNullOrEmptyString(repositoryName, "repositoryName");
|
||||
|
||||
var endpoint = "/repos/{0}/{1}/stats/commit_activity".FormatUri(owner, repositoryName);
|
||||
var activity = await ApiConnection.GetQueuedOperation<IReadOnlyList<WeeklyCommitActivity>>(endpoint,cancellationToken);
|
||||
var activity = await ApiConnection.GetQueuedOperation<WeeklyCommitActivity>(endpoint,cancellationToken);
|
||||
return new CommitActivity(activity);
|
||||
}
|
||||
|
||||
@@ -99,7 +100,7 @@ namespace Octokit
|
||||
Ensure.ArgumentNotNullOrEmptyString(repositoryName, "repositoryName");
|
||||
|
||||
var endpoint = "/repos/{0}/{1}/stats/code_frequency".FormatUri(owner, repositoryName);
|
||||
var rawFrequencies = await ApiConnection.GetQueuedOperation<IEnumerable<long[]>>(endpoint,cancellationToken);
|
||||
var rawFrequencies = await ApiConnection.GetQueuedOperation<long[]>(endpoint,cancellationToken);
|
||||
return new CodeFrequency(rawFrequencies);
|
||||
}
|
||||
|
||||
@@ -127,7 +128,8 @@ namespace Octokit
|
||||
Ensure.ArgumentNotNullOrEmptyString(repositoryName, "repositoryName");
|
||||
|
||||
var endpoint = "/repos/{0}/{1}/stats/participation".FormatUri(owner, repositoryName);
|
||||
return await ApiConnection.GetQueuedOperation<Participation>(endpoint,cancellationToken);
|
||||
var result = await ApiConnection.GetQueuedOperation<Participation>(endpoint,cancellationToken);
|
||||
return result.FirstOrDefault();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -154,7 +156,7 @@ namespace Octokit
|
||||
Ensure.ArgumentNotNullOrEmptyString(repositoryName, "repositoryName");
|
||||
|
||||
var endpoint = "/repos/{0}/{1}/stats/punch_card".FormatUri(owner, repositoryName);
|
||||
var punchCardData = await ApiConnection.GetQueuedOperation<IEnumerable<int[]>>(endpoint, cancellationToken);
|
||||
var punchCardData = await ApiConnection.GetQueuedOperation<int[]>(endpoint, cancellationToken);
|
||||
return new PunchCard(punchCardData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,7 @@ namespace Octokit.Helpers
|
||||
/// </summary>
|
||||
public static class UnixTimestampExtensions
|
||||
{
|
||||
// Unix Epoch is January 1, 1970 00:00 -0:00
|
||||
const long unixEpochTicks = 621355968000000000;
|
||||
static readonly DateTimeOffset epoch = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
|
||||
|
||||
/// <summary>
|
||||
/// Convert a Unix tick to a <see cref="DateTimeOffset"/> with UTC offset
|
||||
@@ -16,7 +15,7 @@ namespace Octokit.Helpers
|
||||
/// <param name="unixTime">UTC tick</param>
|
||||
public static DateTimeOffset FromUnixTime(this long unixTime)
|
||||
{
|
||||
return new DateTimeOffset(unixTime * TimeSpan.TicksPerSecond + unixEpochTicks, TimeSpan.Zero);
|
||||
return epoch.AddSeconds(unixTime);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -25,7 +24,7 @@ namespace Octokit.Helpers
|
||||
/// <param name="date">Date Time with UTC offset</param>
|
||||
public static long ToUnixTime(this DateTimeOffset date)
|
||||
{
|
||||
return (date.Ticks - unixEpochTicks) / TimeSpan.TicksPerSecond;
|
||||
return Convert.ToInt64((date.ToUniversalTime() - epoch).TotalSeconds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -422,33 +423,36 @@ namespace Octokit
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes a GET to the API object at the specified URI. This operation is appropriate for
|
||||
/// API calls which queue long running calculations.
|
||||
/// It expects the API to respond with an initial 202 Accepted, and queries again until a
|
||||
/// 200 OK is received.
|
||||
/// Executes a GET to the API object at the specified URI. This operation is appropriate for API calls which
|
||||
/// queue long running calculations and return a collection of a resource.
|
||||
/// It expects the API to respond with an initial 202 Accepted, and queries again until a 200 OK is received.
|
||||
/// It returns an empty collection if it receives a 204 No Content response.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The API resource's type.</typeparam>
|
||||
/// <param name="uri">URI of the API resource to update</param>
|
||||
/// <param name="cancellationToken">A token used to cancel this potentially long running request</param>
|
||||
/// <returns>The updated API resource.</returns>
|
||||
/// <exception cref="ApiException">Thrown when an API error occurs.</exception>
|
||||
public async Task<T> GetQueuedOperation<T>(Uri uri, CancellationToken cancellationToken)
|
||||
public async Task<IReadOnlyList<T>> GetQueuedOperation<T>(Uri uri, CancellationToken cancellationToken)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
Ensure.ArgumentNotNull(uri, "uri");
|
||||
|
||||
var response = await Connection.GetResponse<T>(uri, cancellationToken);
|
||||
var response = await Connection.GetResponse<IReadOnlyList<T>>(uri, cancellationToken);
|
||||
|
||||
switch (response.HttpResponse.StatusCode)
|
||||
{
|
||||
case HttpStatusCode.Accepted:
|
||||
continue;
|
||||
case HttpStatusCode.NoContent:
|
||||
return new ReadOnlyCollection<T>(new T[] {});
|
||||
case HttpStatusCode.OK:
|
||||
return response.Body;
|
||||
}
|
||||
|
||||
throw new ApiException("Queued Operations expect status codes of Accepted or OK.", response.HttpResponse.StatusCode);
|
||||
throw new ApiException("Queued Operations expect status codes of Accepted, No Content, or OK.",
|
||||
response.HttpResponse.StatusCode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -252,16 +252,16 @@ namespace Octokit
|
||||
Task<string> GetRedirect(Uri uri);
|
||||
|
||||
/// <summary>
|
||||
/// Executes a GET to the API object at the specified URI. This operation is appropriate for
|
||||
/// API calls which queue long running calculations.
|
||||
/// It expects the API to respond with an initial 202 Accepted, and queries again until a
|
||||
/// 200 OK is received.
|
||||
/// Executes a GET to the API object at the specified URI. This operation is appropriate for API calls which
|
||||
/// queue long running calculations and return a collection of a resource.
|
||||
/// It expects the API to respond with an initial 202 Accepted, and queries again until a 200 OK is received.
|
||||
/// It returns an empty collection if it receives a 204 No Content response.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The API resource's type.</typeparam>
|
||||
/// <param name="uri">URI of the API resource to update</param>
|
||||
/// <param name="cancellationToken">A token used to cancel this potentially long running request</param>
|
||||
/// <returns>The updated API resource.</returns>
|
||||
/// <exception cref="ApiException">Thrown when an API error occurs.</exception>
|
||||
Task<T> GetQueuedOperation<T>(Uri uri,CancellationToken cancellationToken);
|
||||
Task<IReadOnlyList<T>> GetQueuedOperation<T>(Uri uri, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user