Skip to content

Commit

Permalink
Return all files from a commit (#1679)
Browse files Browse the repository at this point in the history
* Fix for #1669

* Doc updates

* Add test data

* Spotless

* Javadoc changes

* Test comment fixes

* PR review changes

* Add required default constructor

* Update GHCommitFileIterable.java

---------

Co-authored-by: Steve <steve@slug.home>
Co-authored-by: Liam Newman <bitwiseman@gmail.com>
  • Loading branch information
3 people committed Jun 30, 2023
1 parent c494891 commit e45932d
Show file tree
Hide file tree
Showing 81 changed files with 14,618 additions and 4 deletions.
24 changes: 22 additions & 2 deletions src/main/java/org/kohsuke/github/GHCommit.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
*/
@SuppressFBWarnings(value = { "NP_UNWRITTEN_FIELD", "UWF_UNWRITTEN_FIELD" }, justification = "JSON API")
public class GHCommit {

private GHRepository owner;

private ShortInfo commit;
Expand Down Expand Up @@ -269,7 +270,7 @@ static class User {
}

/** The sha. */
String url, html_url, sha;
String url, html_url, sha, message;

/** The files. */
List<File> files;
Expand Down Expand Up @@ -308,6 +309,7 @@ public GHCommit() {
sha = commit.getSha();
url = commit.getUrl();
parents = commit.getParents();
message = commit.getMessage();
}

/**
Expand Down Expand Up @@ -414,10 +416,28 @@ public URL getUrl() {
* @return Can be empty but never null.
* @throws IOException
* on error
* @deprecated Use {@link #listFiles()} instead.
*/
@Deprecated
public List<File> getFiles() throws IOException {
return listFiles().toList();
}

/**
* List of files changed/added/removed in this commit. Uses a paginated list if the files returned by GitHub exceed
* 300 in quantity.
*
* @return the List of files
* @see <a href="https://docs.github.com/en/rest/commits/commits?apiVersion=2022-11-28#get-a-commit">Get a
* commit</a>
* @throws IOException
* on error
*/
public PagedIterable<File> listFiles() throws IOException {

populate();
return files != null ? Collections.unmodifiableList(files) : Collections.<File>emptyList();

return new GHCommitFileIterable(owner, sha, files);
}

/**
Expand Down
96 changes: 96 additions & 0 deletions src/main/java/org/kohsuke/github/GHCommitFileIterable.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package org.kohsuke.github;

import org.kohsuke.github.GHCommit.File;

import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import javax.annotation.Nonnull;

/**
* Iterable for commit listing.
*
* @author Stephen Horgan
*/
class GHCommitFileIterable extends PagedIterable<GHCommit.File> {

/**
* Number of files returned in the commit response. If there are more files than this, the response will include
* pagination link headers for the remaining files.
*/
private static final int GH_FILE_LIMIT_PER_COMMIT_PAGE = 300;

private final GHRepository owner;
private final String sha;
private final File[] files;

/**
* Instantiates a new GH commit iterable.
*
* @param owner
* the owner
* @param sha
* the SHA of the commit
* @param files
* the list of files initially populated
*/
public GHCommitFileIterable(GHRepository owner, String sha, List<File> files) {
this.owner = owner;
this.sha = sha;
this.files = files != null ? files.toArray(new File[0]) : null;
}

/**
* Iterator.
*
* @param pageSize
* the page size
* @return the paged iterator
*/
@Nonnull
@Override
public PagedIterator<GHCommit.File> _iterator(int pageSize) {

Iterator<GHCommit.File[]> pageIterator;

if (files != null && files.length < GH_FILE_LIMIT_PER_COMMIT_PAGE) {
// create a page iterator that only provides one page
pageIterator = Collections.singleton(files).iterator();
} else {
// page size is controlled by the server for this iterator, do not allow it to be set by the caller
pageSize = 0;

GitHubRequest request = owner.root()
.createRequest()
.withUrlPath(owner.getApiTailUrl("commits/" + sha))
.build();

pageIterator = adapt(
GitHubPageIterator.create(owner.root().getClient(), GHCommitFilesPage.class, request, pageSize));
}

return new PagedIterator<>(pageIterator, null);
}

/**
* Adapt.
*
* @param base
* the base commit page
* @return the iterator
*/
protected Iterator<GHCommit.File[]> adapt(final Iterator<GHCommitFilesPage> base) {
return new Iterator<GHCommit.File[]>() {

public boolean hasNext() {
return base.hasNext();
}

public GHCommit.File[] next() {
GHCommitFilesPage v = base.next();
return v.getFiles();
}
};
}
}
30 changes: 30 additions & 0 deletions src/main/java/org/kohsuke/github/GHCommitFilesPage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.kohsuke.github;

import org.kohsuke.github.GHCommit.File;

/**
* Represents the array of files in a commit returned by github.
*
* @author Stephen Horgan
*/
class GHCommitFilesPage {
private File[] files;

public GHCommitFilesPage() {
}

public GHCommitFilesPage(File[] files) {
this.files = files;
}

/**
* Gets the files.
*
* @param owner
* the owner
* @return the files
*/
File[] getFiles() {
return files;
}
}
4 changes: 4 additions & 0 deletions src/main/java/org/kohsuke/github/GHCompare.java
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,10 @@ public PagedIterator<Commit> _iterator(int pageSize) {
/**
* Gets an array of files.
*
* By default, the file array is limited to 300 results. To retrieve the full list of files, iterate over each
* commit returned by {@link GHCompare#listCommits} and use {@link GHCommit#listFiles} to get the files for each
* commit.
*
* @return A copy of the array being stored in the class.
*/
public GHCommit.File[] getFiles() {
Expand Down
62 changes: 60 additions & 2 deletions src/test/java/org/kohsuke/github/CommitTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ public void lastStatus() throws IOException {
}

/**
* List files.
* Test get files.
*
* @throws Exception
* the exception
*/
@Test // issue 230
public void listFiles() throws Exception {
public void getFiles() throws Exception {
GHRepository repo = gitHub.getRepository("stapler/stapler");
PagedIterable<GHCommit> commits = repo.queryCommits().path("pom.xml").list();
for (GHCommit commit : Iterables.limit(commits, 10)) {
Expand All @@ -47,6 +47,49 @@ public void listFiles() throws Exception {
}
}

/**
* Test list files where there are less than 300 files in a commit.
*
* @throws Exception
* the exception
*/
@Test // issue 1669
public void listFilesWhereCommitHasSmallChange() throws Exception {
GHRepository repo = getRepository();
GHCommit commit = repo.getCommit("dabf0e89fe7107d6e294a924561533ecf80f2384");

assertThat(commit.listFiles().toList().size(), equalTo(28));
}

/**
* Test list files where there are more than 300 files in a commit.
*
* @throws Exception
* the exception
*/
@Test // issue 1669
public void listFilesWhereCommitHasLargeChange() throws Exception {
GHRepository repo = getRepository();
GHCommit commit = repo.getCommit("b83812aa76bb7c3c43da96fbf8aec1e45db87624");

assertThat(commit.listFiles().toList().size(), equalTo(691));
}

/**
* Tests the commit message.
*
* @throws Exception
* the exception
*/
@Test
public void getMessage() throws Exception {
GHRepository repo = getRepository();
GHCommit commit = repo.getCommit("dabf0e89fe7107d6e294a924561533ecf80f2384");

assertThat(commit.getCommitShortInfo().getMessage(), notNullValue());
assertThat(commit.getCommitShortInfo().getMessage(), equalTo("A commit with a few files"));
}

/**
* Test query commits.
*
Expand Down Expand Up @@ -288,4 +331,19 @@ public void commitDateNotNull() throws Exception {
assertThat(commit.getCommitShortInfo().getCommitDate(),
equalTo(commit.getCommitShortInfo().getCommitter().getDate()));
}

/**
* Gets the repository.
*
* @return the repository
* @throws IOException
* Signals that an I/O exception has occurred.
*/
protected GHRepository getRepository() throws IOException {
return getRepository(gitHub);
}

private GHRepository getRepository(GitHub gitHub) throws IOException {
return gitHub.getOrganization("hub4j-test-org").getRepository("CommitTest");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"login": "hub4j-test-org",
"id": 7544739,
"node_id": "MDEyOk9yZ2FuaXphdGlvbjc1NDQ3Mzk=",
"url": "https://api.github.com/orgs/hub4j-test-org",
"repos_url": "https://api.github.com/orgs/hub4j-test-org/repos",
"events_url": "https://api.github.com/orgs/hub4j-test-org/events",
"hooks_url": "https://api.github.com/orgs/hub4j-test-org/hooks",
"issues_url": "https://api.github.com/orgs/hub4j-test-org/issues",
"members_url": "https://api.github.com/orgs/hub4j-test-org/members{/member}",
"public_members_url": "https://api.github.com/orgs/hub4j-test-org/public_members{/member}",
"avatar_url": "https://avatars.githubusercontent.com/u/7544739?v=4",
"description": "Hub4j Test Org Description (this could be null or blank too)",
"name": "Hub4j Test Org Name (this could be null or blank too)",
"company": null,
"blog": "https://hub4j.url.io/could/be/null",
"location": "Hub4j Test Org Location (this could be null or blank too)",
"email": "hub4jtestorgemail@could.be.null.com",
"twitter_username": null,
"is_verified": false,
"has_organization_projects": true,
"has_repository_projects": true,
"public_repos": 26,
"public_gists": 0,
"followers": 1,
"following": 0,
"html_url": "https://github.com/hub4j-test-org",
"created_at": "2014-05-10T19:39:11Z",
"updated_at": "2020-06-04T05:56:10Z",
"type": "Organization"
}
Loading

0 comments on commit e45932d

Please sign in to comment.