diff --git a/Octokit.Reactive/Clients/IObservableReleasesClient.cs b/Octokit.Reactive/Clients/IObservableReleasesClient.cs
index a8bfa4cc..242e13d2 100644
--- a/Octokit.Reactive/Clients/IObservableReleasesClient.cs
+++ b/Octokit.Reactive/Clients/IObservableReleasesClient.cs
@@ -18,6 +18,19 @@ namespace Octokit.Reactive
/// The list of s for the specified repository.
IObservable GetAll(string owner, string name);
+ ///
+ /// Gets all s for the specified repository.
+ ///
+ ///
+ /// See the API documentation for more information.
+ ///
+ /// The repository's owner
+ /// The repository's name
+ /// Options for changing the API response
+ /// Thrown when a general API error occurs.
+ /// The list of s for the specified repository.
+ IObservable GetAll(string owner, string name, ApiOptions options);
+
///
/// Gets a single for the specified repository.
///
diff --git a/Octokit.Reactive/Clients/ObservableReleasesClient.cs b/Octokit.Reactive/Clients/ObservableReleasesClient.cs
index dfc9478e..100bd131 100644
--- a/Octokit.Reactive/Clients/ObservableReleasesClient.cs
+++ b/Octokit.Reactive/Clients/ObservableReleasesClient.cs
@@ -36,6 +36,26 @@ namespace Octokit.Reactive
return _connection.GetAndFlattenAllPages(ApiUrls.Releases(owner, name));
}
+ ///
+ /// Gets all s for the specified repository.
+ ///
+ ///
+ /// See the API documentation for more information.
+ ///
+ /// The repository's owner
+ /// The repository's name
+ /// Options for changing the API response
+ /// Thrown when a general API error occurs.
+ /// The list of s for the specified repository.
+ public IObservable GetAll(string owner, string name, ApiOptions options)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(name, "name");
+ Ensure.ArgumentNotNull(options, "options");
+
+ return _connection.GetAndFlattenAllPages(ApiUrls.Releases(owner, name), options);
+ }
+
///
/// Gets a single for the specified repository.
///
diff --git a/Octokit.Reactive/Helpers/ConnectionExtensions.cs b/Octokit.Reactive/Helpers/ConnectionExtensions.cs
index 0094134c..becbf01c 100644
--- a/Octokit.Reactive/Helpers/ConnectionExtensions.cs
+++ b/Octokit.Reactive/Helpers/ConnectionExtensions.cs
@@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
using System.Reactive.Linq;
using System.Reactive.Threading.Tasks;
@@ -12,6 +14,15 @@ namespace Octokit.Reactive.Internal
return GetPages(url, null, (pageUrl, pageParams) => connection.Get>(pageUrl, null, null).ToObservable());
}
+ public static IObservable GetAndFlattenAllPages(this IConnection connection, Uri url, ApiOptions options)
+ {
+ return GetPagesWithOptions(url, options, (pageUrl, o) =>
+ {
+ var parameters = Pagination.Setup(new Dictionary(), options);
+ return connection.Get>(pageUrl, parameters, null).ToObservable();
+ });
+ }
+
public static IObservable GetAndFlattenAllPages(this IConnection connection, Uri url, IDictionary parameters)
{
return GetPages(url, parameters, (pageUrl, pageParams) => connection.Get>(pageUrl, pageParams, null).ToObservable());
@@ -35,5 +46,24 @@ namespace Octokit.Reactive.Internal
.Where(resp => resp != null)
.SelectMany(resp => resp.Body);
}
+
+ static IObservable GetPagesWithOptions(Uri uri, ApiOptions options,
+ Func>>> getPageFunc)
+ {
+ return getPageFunc(uri, options).Expand(resp =>
+ {
+ var nextPageUri = resp.HttpResponse.ApiInfo.GetNextPageUrl();
+
+ var shouldContinue = Pagination.ShouldContinue(
+ nextPageUri,
+ options);
+
+ return shouldContinue
+ ? Observable.Defer(() => getPageFunc(nextPageUri, null))
+ : Observable.Empty>>();
+ })
+ .Where(resp => resp != null)
+ .SelectMany(resp => resp.Body);
+ }
}
}
diff --git a/Octokit.Reactive/Octokit.Reactive-Mono.csproj b/Octokit.Reactive/Octokit.Reactive-Mono.csproj
index 41db9810..6cf3a026 100644
--- a/Octokit.Reactive/Octokit.Reactive-Mono.csproj
+++ b/Octokit.Reactive/Octokit.Reactive-Mono.csproj
@@ -52,6 +52,9 @@
Helpers\Ensure.cs
+
+ Helpers\Pagination.cs
+
Properties\SolutionInfo.cs
@@ -181,4 +184,4 @@
Octokit-Mono
-
\ No newline at end of file
+
diff --git a/Octokit.Reactive/Octokit.Reactive-MonoAndroid.csproj b/Octokit.Reactive/Octokit.Reactive-MonoAndroid.csproj
index 2a01d4da..146e66b0 100644
--- a/Octokit.Reactive/Octokit.Reactive-MonoAndroid.csproj
+++ b/Octokit.Reactive/Octokit.Reactive-MonoAndroid.csproj
@@ -60,6 +60,9 @@
Helpers\Ensure.cs
+
+ Helpers\Pagination.cs
+
Properties\SolutionInfo.cs
@@ -189,4 +192,4 @@
Octokit-MonoAndroid
-
\ No newline at end of file
+
diff --git a/Octokit.Reactive/Octokit.Reactive-Monotouch.csproj b/Octokit.Reactive/Octokit.Reactive-Monotouch.csproj
index c3855b70..c3d64929 100644
--- a/Octokit.Reactive/Octokit.Reactive-Monotouch.csproj
+++ b/Octokit.Reactive/Octokit.Reactive-Monotouch.csproj
@@ -56,6 +56,9 @@
Helpers\Ensure.cs
+
+ Helpers\Pagination.cs
+
Properties\SolutionInfo.cs
@@ -185,4 +188,4 @@
Octokit-Monotouch
-
\ No newline at end of file
+
diff --git a/Octokit.Reactive/Octokit.Reactive.csproj b/Octokit.Reactive/Octokit.Reactive.csproj
index 4c69b57f..8d1d8e99 100644
--- a/Octokit.Reactive/Octokit.Reactive.csproj
+++ b/Octokit.Reactive/Octokit.Reactive.csproj
@@ -72,6 +72,9 @@
Helpers\Ensure.cs
+
+ Helpers\Pagination.cs
+
Properties\SolutionInfo.cs
diff --git a/Octokit.Tests.Conventions/Exception/ApiOptionsMissingException.cs b/Octokit.Tests.Conventions/Exception/ApiOptionsMissingException.cs
new file mode 100644
index 00000000..61d1111f
--- /dev/null
+++ b/Octokit.Tests.Conventions/Exception/ApiOptionsMissingException.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace Octokit.Tests.Conventions
+{
+ public class ApiOptionsMissingException : Exception
+ {
+ public ApiOptionsMissingException(Type type, IEnumerable methods)
+ : base(CreateMessage(type, methods)) { }
+
+ static string CreateMessage(Type type, IEnumerable methods)
+ {
+ var methodsFormatted = String.Join("\r\n", methods.Select(FormatMethod));
+ return "Methods found on type {0} require an overload which accepts an parameter of type ApiOptions:\r\n{1}"
+ .FormatWithNewLine(
+ type.Name,
+ methodsFormatted);
+ }
+
+ static string FormatMethod(MethodInfo m)
+ {
+ var formattedParameters = m.GetParameters()
+ .Select(p => string.Format("{0} {1}", p.ParameterType.Name, p.Name));
+
+ var parameterList = string.Join(", ", formattedParameters);
+
+ return string.Format(" - {0}({1})", m.Name, parameterList);
+ }
+ }
+}
diff --git a/Octokit.Tests.Conventions/ModelTests.cs b/Octokit.Tests.Conventions/ModelTests.cs
index f126e8cd..0cfcb3c8 100644
--- a/Octokit.Tests.Conventions/ModelTests.cs
+++ b/Octokit.Tests.Conventions/ModelTests.cs
@@ -95,27 +95,6 @@ namespace Octokit.Tests.Conventions
}
}
- //TODO: This should (probably) be moved to the PaginationTests class that is being introduced in PR #760
- [Theory]
- [MemberData("GetClientInterfaces")]
- public void CheckPaginationGetAllMethodNames(Type clientInterface)
- {
- var methodsOrdered = clientInterface.GetMethodsOrdered();
-
- var methodsThatCanPaginate = methodsOrdered
- .Where(x => x.ReturnType.GetTypeInfo().TypeCategory == TypeCategory.ReadOnlyList)
- .Where(x => x.Name.StartsWith("Get"));
-
- var invalidMethods = methodsThatCanPaginate
- .Where(x => !x.Name.StartsWith("GetAll"))
- .ToList();
-
- if (invalidMethods.Any())
- {
- throw new PaginationGetAllMethodNameMismatchException(clientInterface, invalidMethods);
- }
- }
-
public static IEnumerable