Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 213eff4

Browse filesBrowse files
authored
Merge pull request hub4j#1214 from ravingbool/1209_ghcompare_supports_per_page_and_page+params
1209 GHCompare supports per_page and page params
2 parents 4b37a82 + a60a93f commit 213eff4
Copy full SHA for 213eff4

File tree

Expand file treeCollapse file tree

46 files changed

+59946
-14
lines changed
Filter options

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Dismiss banner
Expand file treeCollapse file tree

46 files changed

+59946
-14
lines changed

‎pom.xml

Copy file name to clipboardExpand all lines: pom.xml
+2-6Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,8 @@
166166
<exclude>org.kohsuke.github.extras.OkHttp3Connector</exclude>
167167
<exclude>org.kohsuke.github.EnforcementLevel</exclude>
168168
<exclude>org.kohsuke.github.GHPerson.1</exclude>
169-
169+
<exclude>org.kohsuke.github.GHCompare.User</exclude>
170+
170171
<!-- TODO: Some coverage, but more needed -->
171172
<exclude>org.kohsuke.github.GHPullRequestReviewBuilder.DraftReviewComment</exclude>
172173
<exclude>org.kohsuke.github.GHIssue.PullRequest</exclude>
@@ -179,11 +180,6 @@
179180
<exclude>org.kohsuke.github.GHBranchProtectionBuilder.Restrictions</exclude>
180181
<exclude>org.kohsuke.github.GHBranchProtection.Restrictions</exclude>
181182
<exclude>org.kohsuke.github.GHCommentAuthorAssociation</exclude>
182-
<exclude>org.kohsuke.github.GHCompare.Commit</exclude>
183-
<exclude>org.kohsuke.github.GHCompare.InnerCommit</exclude>
184-
<exclude>org.kohsuke.github.GHCompare.Tree</exclude>
185-
<exclude>org.kohsuke.github.GHCompare.User</exclude>
186-
<exclude>org.kohsuke.github.GHCompare</exclude>
187183
<exclude>org.kohsuke.github.GHDeployKey</exclude>
188184
<exclude>org.kohsuke.github.GHEmail</exclude>
189185
<exclude>org.kohsuke.github.GHInvitation</exclude>

‎src/main/java/org/kohsuke/github/GHCompare.java

Copy file name to clipboardExpand all lines: src/main/java/org/kohsuke/github/GHCompare.java
+105-4Lines changed: 105 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
package org.kohsuke.github;
22

3+
import com.fasterxml.jackson.annotation.JacksonInject;
34
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
45
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
6+
import org.jetbrains.annotations.NotNull;
57

8+
import java.io.IOException;
9+
import java.net.MalformedURLException;
610
import java.net.URL;
11+
import java.util.Collections;
12+
import java.util.Iterator;
13+
14+
import javax.annotation.Nonnull;
715

816
/**
917
* The model user for comparing 2 commits in the GitHub API.
@@ -21,6 +29,9 @@ public class GHCompare {
2129

2230
private GHRepository owner;
2331

32+
@JacksonInject("GHCompare_usePaginatedCommits")
33+
private boolean usePaginatedCommits;
34+
2435
/**
2536
* Gets url.
2637
*
@@ -123,16 +134,56 @@ public Commit getMergeBaseCommit() {
123134
/**
124135
* Gets an array of commits.
125136
*
137+
* By default, the commit list is limited to 250 results.
138+
*
139+
* Since
140+
* <a href="https://github.blog/changelog/2021-03-22-compare-rest-api-now-supports-pagination/">2021-03-22</a>,
141+
* compare supports pagination of commits. This makes the initial {@link GHCompare} response return faster and
142+
* supports comparisons with more than 250 commits. To read commits progressively using pagination, set
143+
* {@link GHRepository#setCompareUsePaginatedCommits(boolean)} to true before calling
144+
* {@link GHRepository#getCompare(String, String)}.
145+
*
126146
* @return A copy of the array being stored in the class.
127147
*/
128148
public Commit[] getCommits() {
129-
Commit[] newValue = new Commit[commits.length];
130-
System.arraycopy(commits, 0, newValue, 0, commits.length);
131-
return newValue;
149+
try {
150+
return listCommits().withPageSize(100).toArray();
151+
} catch (IOException e) {
152+
throw new GHException(e.getMessage(), e);
153+
}
132154
}
133155

134156
/**
135-
* Gets an array of commits.
157+
* Iterable of commits for this comparison.
158+
*
159+
* By default, the commit list is limited to 250 results.
160+
*
161+
* Since
162+
* <a href="https://github.blog/changelog/2021-03-22-compare-rest-api-now-supports-pagination/">2021-03-22</a>,
163+
* compare supports pagination of commits. This makes the initial {@link GHCompare} response return faster and
164+
* supports comparisons with more than 250 commits. To read commits progressively using pagination, set
165+
* {@link GHRepository#setCompareUsePaginatedCommits(boolean)} to true before calling
166+
* {@link GHRepository#getCompare(String, String)}.
167+
*
168+
* @return iterable of commits
169+
*/
170+
public PagedIterable<Commit> listCommits() {
171+
if (usePaginatedCommits) {
172+
return new GHCompareCommitsIterable();
173+
} else {
174+
// if not using paginated commits, adapt the returned commits array
175+
return new PagedIterable<Commit>() {
176+
@NotNull
177+
@Override
178+
public PagedIterator<Commit> _iterator(int pageSize) {
179+
return new PagedIterator<>(Collections.singleton(commits).iterator(), null);
180+
}
181+
};
182+
}
183+
}
184+
185+
/**
186+
* Gets an array of files.
136187
*
137188
* @return A copy of the array being stored in the class.
138189
*/
@@ -283,4 +334,54 @@ public static class User extends GitUser {
283334
public static enum Status {
284335
behind, ahead, identical, diverged
285336
}
337+
338+
/**
339+
* Iterable for commit listing.
340+
*/
341+
class GHCompareCommitsIterable extends PagedIterable<Commit> {
342+
343+
private GHCompare result;
344+
345+
public GHCompareCommitsIterable() {
346+
}
347+
348+
@Nonnull
349+
@Override
350+
public PagedIterator<Commit> _iterator(int pageSize) {
351+
try {
352+
GitHubRequest request = owner.getRoot()
353+
.createRequest()
354+
.injectMappingValue("GHCompare_usePaginatedCommits", usePaginatedCommits)
355+
.withUrlPath(owner.getApiTailUrl(url.substring(url.lastIndexOf("/compare/"))))
356+
.build();
357+
358+
// page_size must be set for GHCompare commit pagination
359+
if (pageSize == 0) {
360+
pageSize = 10;
361+
}
362+
return new PagedIterator<>(
363+
adapt(GitHubPageIterator
364+
.create(owner.getRoot().getClient(), GHCompare.class, request, pageSize)),
365+
item -> item.wrapUp(owner));
366+
} catch (MalformedURLException e) {
367+
throw new GHException("Malformed URL", e);
368+
}
369+
}
370+
371+
protected Iterator<Commit[]> adapt(final Iterator<GHCompare> base) {
372+
return new Iterator<Commit[]>() {
373+
public boolean hasNext() {
374+
return base.hasNext();
375+
}
376+
377+
public Commit[] next() {
378+
GHCompare v = base.next();
379+
if (result == null) {
380+
result = v;
381+
}
382+
return v.commits;
383+
}
384+
};
385+
}
386+
}
286387
}

‎src/main/java/org/kohsuke/github/GHRepository.java

Copy file name to clipboardExpand all lines: src/main/java/org/kohsuke/github/GHRepository.java
+24-4Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ public class GHRepository extends GHObject {
125125
private GHRepository source, parent;
126126

127127
private Boolean isTemplate;
128+
private boolean compareUsePaginatedCommits;
128129

129130
static GHRepository read(GitHub root, String owner, String name) throws IOException {
130131
return root.createRequest().withUrlPath("/repos/" + owner + '/' + name).fetch(GHRepository.class).wrap(root);
@@ -1642,6 +1643,21 @@ public GHHook getHook(int id) throws IOException {
16421643
return GHHooks.repoContext(this, owner).getHook(id);
16431644
}
16441645

1646+
/**
1647+
* Sets {@link #getCompare(String, String)} to return a {@link GHCompare} that uses a paginated commit list instead
1648+
* of limiting to 250 results.
1649+
*
1650+
* By default, {@link GHCompare} returns all commits in the comparison as part of the request, limited to 250
1651+
* results. More recently GitHub added the ability to return the commits as a paginated query allowing for more than
1652+
* 250 results.
1653+
*
1654+
* @param value
1655+
* true if you want commits returned in paginated form.
1656+
*/
1657+
public void setCompareUsePaginatedCommits(boolean value) {
1658+
compareUsePaginatedCommits = value;
1659+
}
1660+
16451661
/**
16461662
* Gets a comparison between 2 points in the repository. This would be similar to calling
16471663
* <code>git log id1...id2</code> against a local repository.
@@ -1656,9 +1672,14 @@ public GHHook getHook(int id) throws IOException {
16561672
* on failure communicating with GitHub
16571673
*/
16581674
public GHCompare getCompare(String id1, String id2) throws IOException {
1659-
GHCompare compare = root.createRequest()
1660-
.withUrlPath(getApiTailUrl(String.format("compare/%s...%s", id1, id2)))
1661-
.fetch(GHCompare.class);
1675+
final Requester requester = root.createRequest()
1676+
.withUrlPath(getApiTailUrl(String.format("compare/%s...%s", id1, id2)));
1677+
1678+
if (compareUsePaginatedCommits) {
1679+
requester.with("per_page", 1).with("page", 1);
1680+
}
1681+
requester.injectMappingValue("GHCompare_usePaginatedCommits", compareUsePaginatedCommits);
1682+
GHCompare compare = requester.fetch(GHCompare.class);
16621683
return compare.wrap(this);
16631684
}
16641685

@@ -1705,7 +1726,6 @@ public GHCompare getCompare(GHBranch id1, GHBranch id2) throws IOException {
17051726
}
17061727

17071728
return getCompare(id1.getName(), id2.getName());
1708-
17091729
}
17101730

17111731
/**

‎src/test/java/org/kohsuke/github/GHRepositoryTest.java

Copy file name to clipboardExpand all lines: src/test/java/org/kohsuke/github/GHRepositoryTest.java
+119Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -866,4 +866,123 @@ public void getLastCommitStatus() throws Exception {
866866
assertThat(status.getState(), equalTo(GHCommitState.SUCCESS));
867867
assertThat(status.getContext(), equalTo("ci/circleci: build"));
868868
}
869+
870+
@Test
871+
public void listCommitsBetween() throws Exception {
872+
GHRepository repository = getRepository();
873+
int startingCount = mockGitHub.getRequestCount();
874+
GHCompare compare = repository.getCompare("e46a9f3f2ac55db96de3c5c4706f2813b3a96465",
875+
"8051615eff597f4e49f4f47625e6fc2b49f26bfc");
876+
int actualCount = 0;
877+
for (GHCompare.Commit item : compare.listCommits().withPageSize(5)) {
878+
assertThat(item, notNullValue());
879+
actualCount++;
880+
}
881+
assertThat(compare.getTotalCommits(), is(9));
882+
assertThat(actualCount, is(9));
883+
assertThat(mockGitHub.getRequestCount(), equalTo(startingCount + 1));
884+
}
885+
886+
@Test
887+
public void listCommitsBetweenPaginated() throws Exception {
888+
GHRepository repository = getRepository();
889+
int startingCount = mockGitHub.getRequestCount();
890+
repository.setCompareUsePaginatedCommits(true);
891+
GHCompare compare = repository.getCompare("e46a9f3f2ac55db96de3c5c4706f2813b3a96465",
892+
"8051615eff597f4e49f4f47625e6fc2b49f26bfc");
893+
int actualCount = 0;
894+
for (GHCompare.Commit item : compare.listCommits().withPageSize(5)) {
895+
assertThat(item, notNullValue());
896+
actualCount++;
897+
}
898+
assertThat(compare.getTotalCommits(), is(9));
899+
assertThat(actualCount, is(9));
900+
assertThat(mockGitHub.getRequestCount(), equalTo(startingCount + 3));
901+
}
902+
903+
@Test
904+
public void getCommitsBetweenOver250() throws Exception {
905+
GHRepository repository = getRepository();
906+
int startingCount = mockGitHub.getRequestCount();
907+
GHCompare compare = repository.getCompare("4261c42949915816a9f246eb14c3dfd21a637bc2",
908+
"94ff089e60064bfa43e374baeb10846f7ce82f40");
909+
int actualCount = 0;
910+
for (GHCompare.Commit item : compare.getCommits()) {
911+
assertThat(item, notNullValue());
912+
actualCount++;
913+
}
914+
assertThat(compare.getTotalCommits(), is(283));
915+
assertThat(actualCount, is(250));
916+
assertThat(mockGitHub.getRequestCount(), equalTo(startingCount + 1));
917+
918+
// Additional GHCompare checks
919+
assertThat(compare.getAheadBy(), equalTo(283));
920+
assertThat(compare.getBehindBy(), equalTo(0));
921+
assertThat(compare.getStatus(), equalTo(GHCompare.Status.ahead));
922+
assertThat(compare.getDiffUrl().toString(),
923+
endsWith(
924+
"compare/4261c42949915816a9f246eb14c3dfd21a637bc2...94ff089e60064bfa43e374baeb10846f7ce82f40.diff"));
925+
assertThat(compare.getHtmlUrl().toString(),
926+
endsWith(
927+
"compare/4261c42949915816a9f246eb14c3dfd21a637bc2...94ff089e60064bfa43e374baeb10846f7ce82f40"));
928+
assertThat(compare.getPatchUrl().toString(),
929+
endsWith(
930+
"compare/4261c42949915816a9f246eb14c3dfd21a637bc2...94ff089e60064bfa43e374baeb10846f7ce82f40.patch"));
931+
assertThat(compare.getPermalinkUrl().toString(),
932+
endsWith("compare/hub4j-test-org:4261c42...hub4j-test-org:94ff089"));
933+
assertThat(compare.getUrl().toString(),
934+
endsWith(
935+
"compare/4261c42949915816a9f246eb14c3dfd21a637bc2...94ff089e60064bfa43e374baeb10846f7ce82f40"));
936+
937+
assertThat(compare.getBaseCommit().getSHA1(), equalTo("4261c42949915816a9f246eb14c3dfd21a637bc2"));
938+
939+
assertThat(compare.getMergeBaseCommit().getSHA1(), equalTo("4261c42949915816a9f246eb14c3dfd21a637bc2"));
940+
// it appears this field is not present in the returned JSON. Strange.
941+
assertThat(compare.getMergeBaseCommit().getCommit().getSha(), nullValue());
942+
assertThat(compare.getMergeBaseCommit().getCommit().getUrl(),
943+
endsWith("/commits/4261c42949915816a9f246eb14c3dfd21a637bc2"));
944+
assertThat(compare.getMergeBaseCommit().getCommit().getMessage(),
945+
endsWith("[maven-release-plugin] prepare release github-api-1.123"));
946+
assertThat(compare.getMergeBaseCommit().getCommit().getAuthor().getName(), equalTo("Liam Newman"));
947+
assertThat(compare.getMergeBaseCommit().getCommit().getCommitter().getName(), equalTo("Liam Newman"));
948+
949+
assertThat(compare.getMergeBaseCommit().getCommit().getTree().getSha(),
950+
equalTo("5da98090976978c93aba0bdfa550e05675543f99"));
951+
assertThat(compare.getMergeBaseCommit().getCommit().getTree().getUrl(),
952+
endsWith("/git/trees/5da98090976978c93aba0bdfa550e05675543f99"));
953+
954+
assertThat(compare.getFiles().length, equalTo(300));
955+
assertThat(compare.getFiles()[0].getFileName(), equalTo(".github/PULL_REQUEST_TEMPLATE.md"));
956+
assertThat(compare.getFiles()[0].getLinesAdded(), equalTo(8));
957+
assertThat(compare.getFiles()[0].getLinesChanged(), equalTo(15));
958+
assertThat(compare.getFiles()[0].getLinesDeleted(), equalTo(7));
959+
assertThat(compare.getFiles()[0].getFileName(), equalTo(".github/PULL_REQUEST_TEMPLATE.md"));
960+
assertThat(compare.getFiles()[0].getPatch(), startsWith("@@ -1,15 +1,16 @@"));
961+
assertThat(compare.getFiles()[0].getPreviousFilename(), nullValue());
962+
assertThat(compare.getFiles()[0].getStatus(), equalTo("modified"));
963+
assertThat(compare.getFiles()[0].getSha(), equalTo("e4234f5f6f39899282a6ef1edff343ae1269222e"));
964+
965+
assertThat(compare.getFiles()[0].getBlobUrl().toString(),
966+
endsWith("/blob/94ff089e60064bfa43e374baeb10846f7ce82f40/.github/PULL_REQUEST_TEMPLATE.md"));
967+
assertThat(compare.getFiles()[0].getRawUrl().toString(),
968+
endsWith("/raw/94ff089e60064bfa43e374baeb10846f7ce82f40/.github/PULL_REQUEST_TEMPLATE.md"));
969+
}
970+
971+
@Test
972+
public void getCommitsBetweenPaged() throws Exception {
973+
GHRepository repository = getRepository();
974+
int startingCount = mockGitHub.getRequestCount();
975+
repository.setCompareUsePaginatedCommits(true);
976+
GHCompare compare = repository.getCompare("4261c42949915816a9f246eb14c3dfd21a637bc2",
977+
"94ff089e60064bfa43e374baeb10846f7ce82f40");
978+
int actualCount = 0;
979+
for (GHCompare.Commit item : compare.getCommits()) {
980+
assertThat(item, notNullValue());
981+
actualCount++;
982+
}
983+
assertThat(compare.getTotalCommits(), is(283));
984+
assertThat(actualCount, is(283));
985+
assertThat(mockGitHub.getRequestCount(), equalTo(startingCount + 4));
986+
}
987+
869988
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
{
2+
"login": "hub4j-test-org",
3+
"id": 7544739,
4+
"node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=",
5+
"url": "https://api.github.com/orgs/hub4j-test-org",
6+
"repos_url": "https://api.github.com/orgs/hub4j-test-org/repos",
7+
"events_url": "https://api.github.com/orgs/hub4j-test-org/events",
8+
"hooks_url": "https://api.github.com/orgs/hub4j-test-org/hooks",
9+
"issues_url": "https://api.github.com/orgs/hub4j-test-org/issues",
10+
"members_url": "https://api.github.com/orgs/hub4j-test-org/members{/member}",
11+
"public_members_url": "https://api.github.com/orgs/hub4j-test-org/public_members{/member}",
12+
"avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4",
13+
"description": "Hub4j Test Org Description (this could be null or blank too)",
14+
"name": "Hub4j Test Org Name (this could be null or blank too)",
15+
"company": null,
16+
"blog": "https://hub4j.url.io/could/be/null",
17+
"location": "Hub4j Test Org Location (this could be null or blank too)",
18+
"email": "hub4jtestorgemail@could.be.null.com",
19+
"twitter_username": null,
20+
"is_verified": false,
21+
"has_organization_projects": true,
22+
"has_repository_projects": true,
23+
"public_repos": 19,
24+
"public_gists": 0,
25+
"followers": 0,
26+
"following": 0,
27+
"html_url": "https://github.com/hub4j-test-org",
28+
"created_at": "2014-05-10T19:39:11Z",
29+
"updated_at": "2020-06-04T05:56:10Z",
30+
"type": "Organization",
31+
"total_private_repos": 2,
32+
"owned_private_repos": 2,
33+
"private_gists": 0,
34+
"disk_usage": 11979,
35+
"collaborators": 0,
36+
"billing_email": "kk@kohsuke.org",
37+
"default_repository_permission": "none",
38+
"members_can_create_repositories": false,
39+
"two_factor_requirement_enabled": false,
40+
"members_can_create_pages": true,
41+
"members_can_create_public_pages": true,
42+
"members_can_create_private_pages": true,
43+
"plan": {
44+
"name": "free",
45+
"space": 976562499,
46+
"private_repos": 10000,
47+
"filled_seats": 26,
48+
"seats": 3
49+
}
50+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.