diff --git a/pom.xml b/pom.xml
index bf8ec0d4..6f35a659 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
4.0.0
github-client
- 0.4.8
+ 0.4.9
com.spotify
@@ -23,7 +23,7 @@
scm:git:https://github.com/spotify/github-java-client.git
scm:git:git@github.com:spotify/github-java-client.git
scm:https://github.com/spotify/github-java-client/
- v0.4.8
+ v0.4.9
@@ -67,7 +67,7 @@
UTF-8
UTF-8
- 1749819070
+ 1750930802
spotbugsexclude.xml
error
checkstyle.xml
@@ -138,6 +138,11 @@
jsr311-api
${jsr311-api.version}
+
+ org.apache.httpcomponents
+ httpclient
+ 4.5.14
+
com.fasterxml.jackson.core
jackson-annotations
@@ -222,6 +227,12 @@
2.2
test
+
+ com.github.npathai
+ hamcrest-optional
+ 2.0.0
+ test
+
org.junit.jupiter
junit-jupiter-engine
diff --git a/src/main/java/com/spotify/github/v3/clients/GitHubClient.java b/src/main/java/com/spotify/github/v3/clients/GitHubClient.java
index 563dbc17..8d0a7fc2 100644
--- a/src/main/java/com/spotify/github/v3/clients/GitHubClient.java
+++ b/src/main/java/com/spotify/github/v3/clients/GitHubClient.java
@@ -97,6 +97,8 @@ public class GitHubClient {
new TypeReference<>() {};
static final TypeReference> LIST_PR_TYPE_REFERENCE =
new TypeReference<>() {};
+ static final TypeReference>
+ LIST_PR_COMMENT_TYPE_REFERENCE = new TypeReference<>() {};
static final TypeReference> LIST_BRANCHES = new TypeReference<>() {};
static final TypeReference> LIST_REFERENCES = new TypeReference<>() {};
static final TypeReference> LIST_REPOSITORY_INVITATION =
@@ -109,8 +111,7 @@ public class GitHubClient {
static final TypeReference> LIST_PENDING_TEAM_INVITATIONS =
new TypeReference<>() {};
- static final TypeReference> LIST_FILE_ITEMS =
- new TypeReference<>() {};
+ static final TypeReference> LIST_FILE_ITEMS = new TypeReference<>() {};
private static final String GET_ACCESS_TOKEN_URL = "app/installations/%s/access_tokens";
@@ -1090,7 +1091,8 @@ private CompletableFuture generateInstallationToken(
if (response.bodyString() == null) {
throw new RuntimeException(
String.format(
- "Got empty response body when getting an access token from GitHub, HTTP status was: %s",
+ "Got empty response body when getting an access token from GitHub, HTTP"
+ + " status was: %s",
response.statusMessage()));
}
final String text = response.bodyString();
diff --git a/src/main/java/com/spotify/github/v3/clients/GithubPage.java b/src/main/java/com/spotify/github/v3/clients/GithubPage.java
index ee3f4436..3e9e6c3a 100644
--- a/src/main/java/com/spotify/github/v3/clients/GithubPage.java
+++ b/src/main/java/com/spotify/github/v3/clients/GithubPage.java
@@ -36,6 +36,9 @@
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.apache.http.client.utils.URIBuilder;
/**
* Async page implementation for github resources
@@ -44,12 +47,27 @@
*/
public class GithubPage implements AsyncPage {
+ static final int ITEM_PER_PAGE_DEFAULT = 30;
private final GitHubClient github;
private final String path;
private final TypeReference> typeReference;
+ private final int itemsPerPage;
+
+ protected static String formatPath(final String path, final int itemsPerPage) {
+ try {
+ URIBuilder uriBuilder = new URIBuilder(path);
+ if (uriBuilder.getQueryParams().stream().anyMatch(p -> p.getName().equals("per_page"))) {
+ return path;
+ }
+ uriBuilder.addParameter("per_page", Integer.toString(itemsPerPage));
+ return uriBuilder.toString();
+ } catch (Exception e) {
+ return path;
+ }
+ }
/**
- * C'tor.
+ * Constructor.
*
* @param github github client
* @param path resource page path
@@ -57,8 +75,27 @@ public class GithubPage implements AsyncPage {
*/
GithubPage(
final GitHubClient github, final String path, final TypeReference> typeReference) {
+ this.itemsPerPage = ITEM_PER_PAGE_DEFAULT;
+ this.github = github;
+ this.path = formatPath(path, ITEM_PER_PAGE_DEFAULT);
+ this.typeReference = typeReference;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param github github client
+ * @param path resource page path
+ * @param typeReference type reference for deserialization
+ */
+ GithubPage(
+ final GitHubClient github,
+ final String path,
+ final TypeReference> typeReference,
+ final int itemsPerPage) {
+ this.itemsPerPage = itemsPerPage;
this.github = github;
- this.path = path;
+ this.path = formatPath(path, itemsPerPage);
this.typeReference = typeReference;
}
@@ -77,7 +114,7 @@ public CompletableFuture pagination() {
.map(
prevLink ->
pageNumberFromUri(prevLink.url().toString())
- .orElseThrow(
+ .orElseThrow(
() ->
new RuntimeException(
"Could not parse page number from Link header with rel=\"next\"")));
@@ -91,7 +128,7 @@ public CompletableFuture pagination() {
.map(
lastLink ->
pageNumberFromUri(lastLink.url().toString())
- .orElseThrow(
+ .orElseThrow(
() ->
new RuntimeException(
"Could not parse page number from Link "
@@ -121,7 +158,7 @@ public CompletableFuture> nextPage() {
Optional.ofNullable(linkMap.get("next"))
.map(nextLink -> nextLink.url().toString().replaceAll(github.urlFor(""), ""))
.orElseThrow(() -> new NoSuchElementException("Page iteration exhausted"));
- return new GithubPage<>(github, nextPath, typeReference);
+ return new GithubPage<>(github, nextPath, typeReference, itemsPerPage);
});
}
@@ -134,7 +171,7 @@ public CompletableFuture hasNextPage() {
/** {@inheritDoc} */
@Override
public AsyncPage clone() {
- return new GithubPage<>(github, path, typeReference);
+ return new GithubPage<>(github, path, typeReference, itemsPerPage);
}
/** {@inheritDoc} */
@@ -153,19 +190,22 @@ private CompletableFuture