Files
github-api/src/main/java/org/kohsuke/github/GHCommit.java
2020-01-15 19:33:22 -08:00

531 lines
14 KiB
Java

package org.kohsuke.github;
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.IOException;
import java.net.URL;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
/**
* A commit in a repository.
*
* @author Kohsuke Kawaguchi
* @see GHRepository#getCommit(String) GHRepository#getCommit(String)
* @see GHCommitComment#getCommit() GHCommitComment#getCommit()
*/
@SuppressFBWarnings(value = { "NP_UNWRITTEN_FIELD", "UWF_UNWRITTEN_FIELD" }, justification = "JSON API")
public class GHCommit {
private GHRepository owner;
private ShortInfo commit;
/**
* Short summary of this commit.
*/
@SuppressFBWarnings(
value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD",
"UWF_UNWRITTEN_FIELD" },
justification = "JSON API")
public static class ShortInfo {
private GHAuthor author;
private GHAuthor committer;
private String message;
private int comment_count;
static class Tree {
String sha;
}
private Tree tree;
/**
* Gets author.
*
* @return the author
*/
@WithBridgeMethods(value = GHAuthor.class, castRequired = true)
public GitUser getAuthor() {
return author;
}
/**
* Gets authored date.
*
* @return the authored date
*/
public Date getAuthoredDate() {
return GitHub.parseDate(author.date);
}
/**
* Gets committer.
*
* @return the committer
*/
@WithBridgeMethods(value = GHAuthor.class, castRequired = true)
public GitUser getCommitter() {
return committer;
}
/**
* Gets commit date.
*
* @return the commit date
*/
public Date getCommitDate() {
return GitHub.parseDate(committer.date);
}
/**
* Gets message.
*
* @return Commit message.
*/
public String getMessage() {
return message;
}
/**
* Gets comment count.
*
* @return the comment count
*/
public int getCommentCount() {
return comment_count;
}
}
/**
* The type GHAuthor.
*
* @deprecated Use {@link GitUser} instead.
*/
public static class GHAuthor extends GitUser {
private String date;
}
/**
* The type Stats.
*/
public static class Stats {
int total, additions, deletions;
}
/**
* A file that was modified.
*/
@SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "It's being initilized by JSON deserialization")
public static class File {
String status;
int changes, additions, deletions;
String raw_url, blob_url, sha, patch;
String filename, previous_filename;
/**
* Gets lines changed.
*
* @return Number of lines added + removed.
*/
public int getLinesChanged() {
return changes;
}
/**
* Gets lines added.
*
* @return Number of lines added.
*/
public int getLinesAdded() {
return additions;
}
/**
* Gets lines deleted.
*
* @return Number of lines removed.
*/
public int getLinesDeleted() {
return deletions;
}
/**
* Gets status.
*
* @return "modified", "added", or "removed"
*/
public String getStatus() {
return status;
}
/**
* Gets file name.
*
* @return Full path in the repository.
*/
@SuppressFBWarnings(value = "NM_CONFUSING",
justification = "It's a part of the library's API and cannot be renamed")
public String getFileName() {
return filename;
}
/**
* Gets previous filename.
*
* @return Previous path, in case file has moved.
*/
public String getPreviousFilename() {
return previous_filename;
}
/**
* Gets patch.
*
* @return The actual change.
*/
public String getPatch() {
return patch;
}
/**
* Gets raw url.
*
* @return URL like
* 'https://raw.github.com/jenkinsci/jenkins/4eb17c197dfdcf8ef7ff87eb160f24f6a20b7f0e/core/pom.xml' that
* resolves to the actual content of the file.
*/
public URL getRawUrl() {
return GitHub.parseURL(raw_url);
}
/**
* Gets blob url.
*
* @return URL like
* 'https://github.com/jenkinsci/jenkins/blob/1182e2ebb1734d0653142bd422ad33c21437f7cf/core/pom.xml'
* that resolves to the HTML page that describes this file.
*/
public URL getBlobUrl() {
return GitHub.parseURL(blob_url);
}
/**
* Gets sha.
*
* @return [0 -9a-f]{40} SHA1 checksum.
*/
public String getSha() {
return sha;
}
}
/**
* The type Parent.
*/
public static class Parent {
@SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now")
String url;
String sha;
}
static class User {
// TODO: what if someone who doesn't have an account on GitHub makes a commit?
@SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now")
String url, avatar_url, gravatar_id;
@SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now")
int id;
String login;
}
String url, html_url, sha;
List<File> files;
Stats stats;
List<Parent> parents;
User author, committer;
/**
* Gets commit short info.
*
* @return the commit short info
* @throws IOException
* the io exception
*/
public ShortInfo getCommitShortInfo() throws IOException {
if (commit == null)
populate();
return commit;
}
/**
* Gets owner.
*
* @return the repository that contains the commit.
*/
public GHRepository getOwner() {
return owner;
}
/**
* Gets lines changed.
*
* @return the number of lines added + removed.
* @throws IOException
* if the field was not populated and refresh fails
*/
public int getLinesChanged() throws IOException {
populate();
return stats.total;
}
/**
* Gets lines added.
*
* @return Number of lines added.
* @throws IOException
* if the field was not populated and refresh fails
*/
public int getLinesAdded() throws IOException {
populate();
return stats.additions;
}
/**
* Gets lines deleted.
*
* @return Number of lines removed.
* @throws IOException
* if the field was not populated and refresh fails
*/
public int getLinesDeleted() throws IOException {
populate();
return stats.deletions;
}
/**
* Use this method to walk the tree.
*
* @return a GHTree to walk
* @throws IOException
* on error
*/
public GHTree getTree() throws IOException {
return owner.getTree(getCommitShortInfo().tree.sha);
}
/**
* Gets html url.
*
* @return URL of this commit like
* "https://github.com/kohsuke/sandbox-ant/commit/8ae38db0ea5837313ab5f39d43a6f73de3bd9000"
*/
public URL getHtmlUrl() {
return GitHub.parseURL(html_url);
}
/**
* Gets sha 1.
*
* @return [0 -9a-f]{40} SHA1 checksum.
*/
public String getSHA1() {
return sha;
}
/**
* List of files changed/added/removed in this commit.
*
* @return Can be empty but never null.
* @throws IOException
* on error
*/
public List<File> getFiles() throws IOException {
populate();
return files != null ? Collections.unmodifiableList(files) : Collections.<File>emptyList();
}
/**
* Gets parent sha 1 s.
*
* @return SHA1 of parent commit objects.
*/
public List<String> getParentSHA1s() {
if (parents == null)
return Collections.emptyList();
return new AbstractList<String>() {
@Override
public String get(int index) {
return parents.get(index).sha;
}
@Override
public int size() {
return parents.size();
}
};
}
/**
* Resolves the parent commit objects and return them.
*
* @return parent commit objects
* @throws IOException
* on error
*/
public List<GHCommit> getParents() throws IOException {
List<GHCommit> r = new ArrayList<GHCommit>();
for (String sha1 : getParentSHA1s())
r.add(owner.getCommit(sha1));
return r;
}
/**
* Gets author.
*
* @return the author
* @throws IOException
* the io exception
*/
public GHUser getAuthor() throws IOException {
return resolveUser(author);
}
/**
* Gets the date the change was authored on.
*
* @return the date the change was authored on.
* @throws IOException
* if the information was not already fetched and an attempt at fetching the information failed.
*/
public Date getAuthoredDate() throws IOException {
return getCommitShortInfo().getAuthoredDate();
}
/**
* Gets committer.
*
* @return the committer
* @throws IOException
* the io exception
*/
public GHUser getCommitter() throws IOException {
return resolveUser(committer);
}
/**
* Gets the date the change was committed on.
*
* @return the date the change was committed on.
* @throws IOException
* if the information was not already fetched and an attempt at fetching the information failed.
*/
public Date getCommitDate() throws IOException {
return getCommitShortInfo().getCommitDate();
}
private GHUser resolveUser(User author) throws IOException {
if (author == null || author.login == null)
return null;
return owner.root.getUser(author.login);
}
/**
* List comments paged iterable.
*
* @return {@link PagedIterable} with all the commit comments in this repository.
*/
public PagedIterable<GHCommitComment> listComments() {
return owner.root.createRequest()
.withUrlPath(
String.format("/repos/%s/%s/commits/%s/comments", owner.getOwnerName(), owner.getName(), sha))
.toIterable(GHCommitComment[].class, item -> item.wrap(owner));
}
/**
* Creates a commit comment.
* <p>
* I'm not sure how path/line/position parameters interact with each other.
*
* @param body
* body of the comment
* @param path
* path of file being commented on
* @param line
* target line for comment
* @param position
* position on line
* @return created GHCommitComment
* @throws IOException
* if comment is not created
*/
public GHCommitComment createComment(String body, String path, Integer line, Integer position) throws IOException {
GHCommitComment r = owner.root.createRequest()
.method("POST")
.with("body", body)
.with("path", path)
.with("line", line)
.with("position", position)
.withUrlPath(
String.format("/repos/%s/%s/commits/%s/comments", owner.getOwnerName(), owner.getName(), sha))
.fetch(GHCommitComment.class);
return r.wrap(owner);
}
/**
* Create comment gh commit comment.
*
* @param body
* the body
* @return the gh commit comment
* @throws IOException
* the io exception
*/
public GHCommitComment createComment(String body) throws IOException {
return createComment(body, null, null, null);
}
/**
* List statuses paged iterable.
*
* @return status of this commit, newer ones first.
* @throws IOException
* if statuses cannot be read
*/
public PagedIterable<GHCommitStatus> listStatuses() throws IOException {
return owner.listCommitStatuses(sha);
}
/**
* Gets last status.
*
* @return the last status of this commit, which is what gets shown in the UI.
* @throws IOException
* on error
*/
public GHCommitStatus getLastStatus() throws IOException {
return owner.getLastCommitStatus(sha);
}
/**
* Some of the fields are not always filled in when this object is retrieved as a part of another API call.
*
* @throws IOException
* on error
*/
void populate() throws IOException {
if (files == null && stats == null)
owner.root.createRequest().withUrlPath(owner.getApiTailUrl("commits/" + sha)).fetchInto(this);
}
GHCommit wrapUp(GHRepository owner) {
this.owner = owner;
return this;
}
}