mirror of
https://github.com/jlengrand/github-api.git
synced 2026-03-11 08:21:23 +00:00
Compare commits
63 Commits
github-api
...
github-api
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6fc9a546cb | ||
|
|
3f6c225948 | ||
|
|
c7e9650a39 | ||
|
|
fd28a36b74 | ||
|
|
86543c84db | ||
|
|
706cdac4cc | ||
|
|
0b69743792 | ||
|
|
dd54a00172 | ||
|
|
b5514b891a | ||
|
|
31a6eca97f | ||
|
|
8557676561 | ||
|
|
39631461ae | ||
|
|
a124d7f714 | ||
|
|
fff07bf70b | ||
|
|
53d09bb5d8 | ||
|
|
a8ecf0bef0 | ||
|
|
74b3902d5f | ||
|
|
7433ed968e | ||
|
|
ddf2d69a68 | ||
|
|
f5b34861bd | ||
|
|
f0ff31a1af | ||
|
|
8ce76fba62 | ||
|
|
a947672320 | ||
|
|
5496e2b553 | ||
|
|
2f9edc65dd | ||
|
|
6372337456 | ||
|
|
b843606ebe | ||
|
|
7cda083b31 | ||
|
|
095604d4ca | ||
|
|
7e799d02e3 | ||
|
|
7f4612f872 | ||
|
|
6f6ff56338 | ||
|
|
27701a75d9 | ||
|
|
3717d2ed32 | ||
|
|
3a9b6665ee | ||
|
|
bbc42f8898 | ||
|
|
f6aea47c2c | ||
|
|
23069ac2fc | ||
|
|
0b2fdc598b | ||
|
|
aac30b923c | ||
|
|
318caf6123 | ||
|
|
6898893ffb | ||
|
|
cb34f4e91f | ||
|
|
0da4b320f1 | ||
|
|
facb5bd13e | ||
|
|
22bc768868 | ||
|
|
a9b6f7bc9c | ||
|
|
830fb7192d | ||
|
|
e8ff7a4ae8 | ||
|
|
dac2a56671 | ||
|
|
2718cf5ccb | ||
|
|
202a5d435c | ||
|
|
58af8d0e90 | ||
|
|
b950be9626 | ||
|
|
222277ae0a | ||
|
|
fbcf3a17b4 | ||
|
|
748cbdd03b | ||
|
|
57b26b6a21 | ||
|
|
a4026d46ce | ||
|
|
696daf7387 | ||
|
|
4a507a5625 | ||
|
|
ac1dd9a0ee | ||
|
|
44f1038516 |
2
README
2
README
@@ -1,3 +1,3 @@
|
||||
Java API for GitHub
|
||||
|
||||
See http://kohsuke.org/github-api/ for more details
|
||||
See http://github-api.kohsuke.org/ for more details
|
||||
|
||||
10
pom.xml
10
pom.xml
@@ -3,11 +3,11 @@
|
||||
<parent>
|
||||
<groupId>org.kohsuke</groupId>
|
||||
<artifactId>pom</artifactId>
|
||||
<version>1</version>
|
||||
<version>3</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>github-api</artifactId>
|
||||
<version>1.16</version>
|
||||
<version>1.24</version>
|
||||
<name>GitHub API for Java</name>
|
||||
<url>http://github-api.kohsuke.org/</url>
|
||||
<description>GitHub API for Java</description>
|
||||
@@ -77,6 +77,12 @@
|
||||
<version>1.4</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.kohsuke.stapler</groupId>
|
||||
<artifactId>stapler-jetty</artifactId>
|
||||
<version>1.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<reporting>
|
||||
|
||||
@@ -6,12 +6,19 @@ package org.kohsuke.github;
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
enum ApiVersion {
|
||||
V2("https://github.com/api/v2/json"),
|
||||
V3("https://api.github.com");
|
||||
|
||||
V2("https://?/api/v2/json"),
|
||||
V3("https://api.?");
|
||||
|
||||
final String url;
|
||||
final String templateUrl;
|
||||
|
||||
ApiVersion(String url) {
|
||||
this.url = url;
|
||||
ApiVersion(String templateUrl) {
|
||||
this.templateUrl = templateUrl;
|
||||
}
|
||||
|
||||
public String getApiVersionBaseUrl(String githubServer) {
|
||||
|
||||
return templateUrl.replaceFirst("\\?", githubServer);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
51
src/main/java/org/kohsuke/github/GHBranch.java
Normal file
51
src/main/java/org/kohsuke/github/GHBranch.java
Normal file
@@ -0,0 +1,51 @@
|
||||
package org.kohsuke.github;
|
||||
|
||||
/**
|
||||
* A branch in a repository.
|
||||
*
|
||||
* @author Yusuke Kokubo
|
||||
*/
|
||||
public class GHBranch {
|
||||
private GitHub root;
|
||||
private GHRepository owner;
|
||||
|
||||
private String name;
|
||||
private Commit commit;
|
||||
|
||||
public static class Commit {
|
||||
String sha,url;
|
||||
}
|
||||
|
||||
public GitHub getRoot() {
|
||||
return root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Repository that this branch is in.
|
||||
*/
|
||||
public GHRepository getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* The commit that this branch currently points to.
|
||||
*/
|
||||
public String getSHA1() {
|
||||
return commit.sha;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Branch:" + name + " in " + owner.getUrl();
|
||||
}
|
||||
|
||||
/*package*/ GHBranch wrap(GHRepository repo) {
|
||||
this.owner = repo;
|
||||
this.root = repo.root;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
243
src/main/java/org/kohsuke/github/GHCommit.java
Normal file
243
src/main/java/org/kohsuke/github/GHCommit.java
Normal file
@@ -0,0 +1,243 @@
|
||||
package org.kohsuke.github;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.kohsuke.github.ApiVersion.V3;
|
||||
|
||||
/**
|
||||
* A commit in a repository.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
* @see GHRepository#getCommit(String)
|
||||
* @see GHCommitComment#getCommit()
|
||||
*/
|
||||
public class GHCommit {
|
||||
private GHRepository owner;
|
||||
|
||||
public static class Stats {
|
||||
int total,additions,deletions;
|
||||
}
|
||||
|
||||
/**
|
||||
* A file that was modified.
|
||||
*/
|
||||
public static class File {
|
||||
String status;
|
||||
int changes,additions,deletions;
|
||||
String raw_url, blob_url, filename, sha, patch;
|
||||
|
||||
/**
|
||||
* Number of lines added + removed.
|
||||
*/
|
||||
public int getLinesChanged() {
|
||||
return changes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of lines added.
|
||||
*/
|
||||
public int getLinesAdded() {
|
||||
return additions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of lines removed.
|
||||
*/
|
||||
public int getLinesDeleted() {
|
||||
return deletions;
|
||||
}
|
||||
|
||||
/**
|
||||
* "modified", "added", or "deleted"
|
||||
*/
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Just the base name and the extension without any directory name.
|
||||
*/
|
||||
public String getFileName() {
|
||||
return filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual change.
|
||||
*/
|
||||
public String getPatch() {
|
||||
return patch;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* [0-9a-f]{40} SHA1 checksum.
|
||||
*/
|
||||
public String getSha() {
|
||||
return sha;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Parent {
|
||||
String url,sha;
|
||||
}
|
||||
|
||||
static class User {
|
||||
// TODO: what if someone who doesn't have an account on GitHub makes a commit?
|
||||
String url,avatar_url,login,gravatar_id;
|
||||
int id;
|
||||
}
|
||||
|
||||
String url,sha;
|
||||
List<File> files;
|
||||
Stats stats;
|
||||
List<Parent> parents;
|
||||
User author,committer;
|
||||
|
||||
/**
|
||||
* The repository that contains the commit.
|
||||
*/
|
||||
public GHRepository getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of lines added + removed.
|
||||
*/
|
||||
public int getLinesChanged() {
|
||||
return stats.total;
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of lines added.
|
||||
*/
|
||||
public int getLinesAdded() {
|
||||
return stats.additions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of lines removed.
|
||||
*/
|
||||
public int getLinesDeleted() {
|
||||
return stats.deletions;
|
||||
}
|
||||
|
||||
/**
|
||||
* [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.
|
||||
*/
|
||||
public List<File> getFiles() {
|
||||
return files!=null ? Collections.unmodifiableList(files) : Collections.<File>emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the 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.
|
||||
*/
|
||||
public List<GHCommit> getParents() throws IOException {
|
||||
List<GHCommit> r = new ArrayList<GHCommit>();
|
||||
for (String sha1 : getParentSHA1s())
|
||||
r.add(owner.getCommit(sha1));
|
||||
return r;
|
||||
}
|
||||
|
||||
public GHUser getAuthor() throws IOException {
|
||||
return resolveUser(author);
|
||||
}
|
||||
|
||||
public GHUser getCommitter() throws IOException {
|
||||
return resolveUser(committer);
|
||||
}
|
||||
|
||||
private GHUser resolveUser(User author) throws IOException {
|
||||
if (author==null || author.login==null) return null;
|
||||
return owner.root.getUser(author.login);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists up all the commit comments in this repository.
|
||||
*/
|
||||
public PagedIterable<GHCommitComment> listComments() {
|
||||
return new PagedIterable<GHCommitComment>() {
|
||||
public PagedIterator<GHCommitComment> iterator() {
|
||||
return new PagedIterator<GHCommitComment>(owner.root.retrievePaged(String.format("/repos/%s/%s/commits/%s/comments",owner.getOwnerName(),owner.getName(),sha),GHCommitComment[].class,false,V3)) {
|
||||
@Override
|
||||
protected void wrapUp(GHCommitComment[] page) {
|
||||
for (GHCommitComment c : page)
|
||||
c.wrap(owner);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a commit comment.
|
||||
*
|
||||
* I'm not sure how path/line/position parameters interact with each other.
|
||||
*/
|
||||
public GHCommitComment createComment(String body, String path, Integer line, Integer position) throws IOException {
|
||||
GHCommitComment r = new Poster(owner.root,V3)
|
||||
.with("body",body)
|
||||
.with("path",path)
|
||||
.with("line",line)
|
||||
.with("position",position)
|
||||
.withCredential()
|
||||
.to(String.format("/repos/%s/%s/commits/%s/comments",owner.getOwnerName(),owner.getName(),sha),GHCommitComment.class);
|
||||
return r.wrap(owner);
|
||||
}
|
||||
|
||||
public GHCommitComment createComment(String body) throws IOException {
|
||||
return createComment(body,null,null,null);
|
||||
}
|
||||
|
||||
GHCommit wrapUp(GHRepository owner) {
|
||||
this.owner = owner;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
125
src/main/java/org/kohsuke/github/GHCommitComment.java
Normal file
125
src/main/java/org/kohsuke/github/GHCommitComment.java
Normal file
@@ -0,0 +1,125 @@
|
||||
package org.kohsuke.github;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Date;
|
||||
|
||||
import static org.kohsuke.github.ApiVersion.V3;
|
||||
|
||||
/**
|
||||
* A comment attached to a commit (or a specific line in a specific file of a commit.)
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
* @see GHRepository#listCommitComments()
|
||||
* @see GHCommit#listComments()
|
||||
* @see GHCommit#createComment(String, String, Integer, Integer)
|
||||
*/
|
||||
public class GHCommitComment {
|
||||
private GHRepository owner;
|
||||
|
||||
String updated_at, created_at;
|
||||
String body, url, html_url, commit_id;
|
||||
Integer line;
|
||||
int id;
|
||||
String path;
|
||||
User user;
|
||||
|
||||
static class User {
|
||||
// TODO: what if someone who doesn't have an account on GitHub makes a commit?
|
||||
String url,avatar_url,login,gravatar_id;
|
||||
int id;
|
||||
}
|
||||
|
||||
public GHRepository getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public Date getCreatedAt() {
|
||||
return GitHub.parseDate(created_at);
|
||||
}
|
||||
|
||||
public Date getUpdatedAt() {
|
||||
return GitHub.parseDate(updated_at);
|
||||
}
|
||||
|
||||
/**
|
||||
* URL like 'https://github.com/kohsuke/sandbox-ant/commit/8ae38db0ea5837313ab5f39d43a6f73de3bd9000#commitcomment-1252827' to
|
||||
* show this commit comment in a browser.
|
||||
*/
|
||||
public URL getHtmlUrl() {
|
||||
return GitHub.parseURL(html_url);
|
||||
}
|
||||
|
||||
public String getSHA1() {
|
||||
return commit_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit comment in the GitHub flavored markdown format.
|
||||
*/
|
||||
public String getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
/**
|
||||
* A commit comment can be on a specific line of a specific file, if so, this field points to a file.
|
||||
* Otherwise null.
|
||||
*/
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* A commit comment can be on a specific line of a specific file, if so, this field points to the line number in the file.
|
||||
* Otherwise -1.
|
||||
*/
|
||||
public int getLine() {
|
||||
return line!=null ? line : -1;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the user who put this comment.
|
||||
*/
|
||||
public GHUser getUser() throws IOException {
|
||||
return owner.root.getUser(user.login);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the commit to which this comment is associated with.
|
||||
*/
|
||||
public GHCommit getCommit() throws IOException {
|
||||
return getOwner().getCommit(getSHA1());
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the body of the commit message.
|
||||
*/
|
||||
public void update(String body) throws IOException {
|
||||
GHCommitComment r = new Poster(owner.root,V3)
|
||||
.with("body",body)
|
||||
.withCredential()
|
||||
.to(getApiTail(),GHCommitComment.class,"PATCH");
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes this comment.
|
||||
*/
|
||||
public void delete() throws IOException {
|
||||
new Poster(owner.root,V3).withCredential().to(getApiTail(),null,"DELETE");
|
||||
}
|
||||
|
||||
private String getApiTail() {
|
||||
return String.format("/repos/%s/%s/comments/%s",owner.getOwnerName(),owner.getName(),id);
|
||||
}
|
||||
|
||||
|
||||
GHCommitComment wrap(GHRepository owner) {
|
||||
this.owner = owner;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ package org.kohsuke.github;
|
||||
public class GHCommitPointer {
|
||||
private String ref, sha, label;
|
||||
private GHUser user;
|
||||
private GHRepository repository;
|
||||
private GHRepository repository/*V2*/,repo/*V3*/;
|
||||
|
||||
/**
|
||||
* This points to the user who owns
|
||||
@@ -45,11 +45,11 @@ public class GHCommitPointer {
|
||||
* The repository that contains the commit.
|
||||
*/
|
||||
public GHRepository getRepository() {
|
||||
return repository;
|
||||
return repo!=null ? repo : repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Named ref to the commit.
|
||||
* Named ref to the commit. This appears to be a "short ref" that doesn't include "refs/heads/" portion.
|
||||
*/
|
||||
public String getRef() {
|
||||
return ref;
|
||||
@@ -68,4 +68,10 @@ public class GHCommitPointer {
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
void wrapUp(GitHub root) {
|
||||
if (user!=null) user.root = root;
|
||||
if (repo!=null) repo.wrap(root);
|
||||
if (repository!=null) repository.wrap(root);
|
||||
}
|
||||
}
|
||||
|
||||
82
src/main/java/org/kohsuke/github/GHEventInfo.java
Normal file
82
src/main/java/org/kohsuke/github/GHEventInfo.java
Normal file
@@ -0,0 +1,82 @@
|
||||
package org.kohsuke.github;
|
||||
|
||||
import org.codehaus.jackson.node.ObjectNode;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Represents an event.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public class GHEventInfo {
|
||||
private GitHub root;
|
||||
|
||||
// we don't want to expose Jackson dependency to the user. This needs databinding
|
||||
private ObjectNode payload;
|
||||
|
||||
private String created_at;
|
||||
private String type;
|
||||
|
||||
// these are all shallow objects
|
||||
private GHEventRepository repo;
|
||||
private GHUser actor;
|
||||
private GHOrganization org;
|
||||
|
||||
/**
|
||||
* Inside the event JSON model, GitHub uses a slightly different format.
|
||||
*/
|
||||
public static class GHEventRepository {
|
||||
private int id;
|
||||
private String url; // repository API URL
|
||||
private String name; // owner/repo
|
||||
}
|
||||
|
||||
public GHEvent getType() {
|
||||
String t = type;
|
||||
if (t.endsWith("Event")) t=t.substring(0,t.length()-5);
|
||||
for (GHEvent e : GHEvent.values()) {
|
||||
if (e.name().replace("_","").equalsIgnoreCase(t))
|
||||
return e;
|
||||
}
|
||||
return null; // unknown event type
|
||||
}
|
||||
|
||||
/*package*/ GHEventInfo wrapUp(GitHub root) {
|
||||
this.root = root;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Date getCreatedAt() {
|
||||
return GitHub.parseDate(created_at);
|
||||
}
|
||||
|
||||
/**
|
||||
* Repository where the change was made.
|
||||
*/
|
||||
public GHRepository getRepository() throws IOException {
|
||||
return root.getRepository(repo.name);
|
||||
}
|
||||
|
||||
public GHUser getActor() throws IOException {
|
||||
return root.getUser(actor.getLogin());
|
||||
}
|
||||
|
||||
public GHOrganization getOrganization() throws IOException {
|
||||
return (org==null || org.getLogin()==null) ? null : root.getOrganization(org.getLogin());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the payload.
|
||||
*
|
||||
* @param type
|
||||
* Specify one of the {@link GHEventPayload} subtype that defines a type-safe access to the payload.
|
||||
* This must match the {@linkplain #getType() event type}.
|
||||
*/
|
||||
public <T extends GHEventPayload> T getPayload(Class<T> type) throws IOException {
|
||||
T v = GitHub.MAPPER.readValue(payload.traverse(), type);
|
||||
v.wrapUp(root);
|
||||
return v;
|
||||
}
|
||||
}
|
||||
46
src/main/java/org/kohsuke/github/GHEventPayload.java
Normal file
46
src/main/java/org/kohsuke/github/GHEventPayload.java
Normal file
@@ -0,0 +1,46 @@
|
||||
package org.kohsuke.github;
|
||||
|
||||
import java.io.Reader;
|
||||
|
||||
/**
|
||||
* Base type for types used in databinding of the event payload.
|
||||
*
|
||||
* @see GitHub#parseEventPayload(Reader, Class)
|
||||
* @see GHEventInfo#getPayload(Class)
|
||||
*/
|
||||
public abstract class GHEventPayload {
|
||||
protected GitHub root;
|
||||
|
||||
/*package*/ GHEventPayload() {
|
||||
}
|
||||
|
||||
/*package*/ void wrapUp(GitHub root) {
|
||||
this.root = root;
|
||||
}
|
||||
|
||||
public static class PullRequest extends GHEventPayload {
|
||||
private String action;
|
||||
private int number;
|
||||
GHPullRequest pull_request;
|
||||
|
||||
public String getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
public int getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
public GHPullRequest getPullRequest() {
|
||||
pull_request.root = root;
|
||||
return pull_request;
|
||||
}
|
||||
|
||||
@Override
|
||||
void wrapUp(GitHub root) {
|
||||
super.wrapUp(root);
|
||||
pull_request.wrapUp(root);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
48
src/main/java/org/kohsuke/github/GHKey.java
Normal file
48
src/main/java/org/kohsuke/github/GHKey.java
Normal file
@@ -0,0 +1,48 @@
|
||||
package org.kohsuke.github;
|
||||
|
||||
import org.apache.commons.lang.builder.ToStringBuilder;
|
||||
|
||||
/**
|
||||
* SSH public key.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public class GHKey {
|
||||
/*package almost final*/ GitHub root;
|
||||
|
||||
private String url, key, title;
|
||||
private boolean verified;
|
||||
private int id;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Something like "https://api.github.com/user/keys/73593"
|
||||
*/
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public boolean isVerified() {
|
||||
return verified;
|
||||
}
|
||||
|
||||
/*package*/ GHKey wrap(GitHub root) {
|
||||
this.root = root;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this).append("title",title).append("id",id).append("key",key).toString();
|
||||
}
|
||||
}
|
||||
73
src/main/java/org/kohsuke/github/GHMilestone.java
Normal file
73
src/main/java/org/kohsuke/github/GHMilestone.java
Normal file
@@ -0,0 +1,73 @@
|
||||
package org.kohsuke.github;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Yusuke Kokubo
|
||||
*
|
||||
*/
|
||||
public class GHMilestone {
|
||||
GitHub root;
|
||||
GHRepository owner;
|
||||
|
||||
GHUser creator;
|
||||
private String state, due_on, title, url, created_at, description;
|
||||
private int closed_issues, open_issues, number;
|
||||
|
||||
public GitHub getRoot() {
|
||||
return root;
|
||||
}
|
||||
|
||||
public GHRepository getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public GHUser getCreator() {
|
||||
return creator;
|
||||
}
|
||||
|
||||
public Date getDueOn() {
|
||||
if (due_on == null) return null;
|
||||
return GitHub.parseDate(due_on);
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public Date getCreatedAt() {
|
||||
return GitHub.parseDate(created_at);
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public int getClosedIssues() {
|
||||
return closed_issues;
|
||||
}
|
||||
|
||||
public int getOpenIssues() {
|
||||
return open_issues;
|
||||
}
|
||||
|
||||
public int getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
public GHMilestoneState getState() {
|
||||
return Enum.valueOf(GHMilestoneState.class, state.toUpperCase(Locale.ENGLISH));
|
||||
}
|
||||
|
||||
public GHMilestone wrap(GHRepository repo) {
|
||||
this.owner = repo;
|
||||
this.root = repo.root;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
11
src/main/java/org/kohsuke/github/GHMilestoneState.java
Normal file
11
src/main/java/org/kohsuke/github/GHMilestoneState.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package org.kohsuke.github;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Yusuke Kokubo
|
||||
*
|
||||
*/
|
||||
public enum GHMilestoneState {
|
||||
OPEN,
|
||||
CLOSED
|
||||
}
|
||||
44
src/main/java/org/kohsuke/github/GHMyself.java
Normal file
44
src/main/java/org/kohsuke/github/GHMyself.java
Normal file
@@ -0,0 +1,44 @@
|
||||
package org.kohsuke.github;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents the account that's logging into GitHub.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public class GHMyself extends GHUser {
|
||||
/**
|
||||
* Returns the read-only list of e-mail addresses configured for you.
|
||||
*
|
||||
* This corresponds to the stuff you configure in https://github.com/settings/emails,
|
||||
* and not to be confused with {@link #getEmail()} that shows your public e-mail address
|
||||
* set in https://github.com/settings/profile
|
||||
*
|
||||
* @return
|
||||
* Always non-null.
|
||||
*/
|
||||
public List<String> getEmails() throws IOException {
|
||||
String[] addresses = root.retrieveWithAuth3("/user/emails",String[].class);
|
||||
return Collections.unmodifiableList(Arrays.asList(addresses));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the read-only list of all the pulic keys of the current user.
|
||||
*
|
||||
* @return
|
||||
* Always non-null.
|
||||
*/
|
||||
public List<GHKey> getPublicKeys() throws IOException {
|
||||
return Collections.unmodifiableList(Arrays.asList(root.retrieveWithAuth3("/user/keys",GHKey[].class)));
|
||||
}
|
||||
|
||||
// public void addEmails(Collection<String> emails) throws IOException {
|
||||
//// new Poster(root,ApiVersion.V3).withCredential().to("/user/emails");
|
||||
// root.retrieveWithAuth3()
|
||||
// }
|
||||
}
|
||||
@@ -1,11 +1,18 @@
|
||||
package org.kohsuke.github;
|
||||
|
||||
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import static org.kohsuke.github.ApiVersion.*;
|
||||
|
||||
/**
|
||||
* Common part of {@link GHUser} and {@link GHOrganization}.
|
||||
*
|
||||
@@ -31,18 +38,48 @@ public abstract class GHPerson {
|
||||
*/
|
||||
public synchronized Map<String,GHRepository> getRepositories() throws IOException {
|
||||
Map<String,GHRepository> repositories = new TreeMap<String, GHRepository>();
|
||||
for (int i=1; ; i++) {
|
||||
GHRepository[] array = root.retrieve3("/users/" + login + "/repos?per_page=100&page=" + i, GHRepository[].class);
|
||||
for (GHRepository r : array) {
|
||||
r.root = root;
|
||||
for (List<GHRepository> batch : iterateRepositories(100)) {
|
||||
for (GHRepository r : batch)
|
||||
repositories.put(r.getName(),r);
|
||||
}
|
||||
if (array.length==0) break;
|
||||
}
|
||||
|
||||
return Collections.unmodifiableMap(repositories);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads repository list in a pagenated fashion.
|
||||
*
|
||||
* <p>
|
||||
* For a person with a lot of repositories, GitHub returns the list of repositories in a pagenated fashion.
|
||||
* Unlike {@link #getRepositories()}, this method allows the caller to start processing data as it arrives.
|
||||
*
|
||||
* Every {@link Iterator#next()} call results in I/O. Exceptions that occur during the processing is wrapped
|
||||
* into {@link Error}.
|
||||
*/
|
||||
public synchronized Iterable<List<GHRepository>> iterateRepositories(final int pageSize) {
|
||||
return new Iterable<List<GHRepository>>() {
|
||||
public Iterator<List<GHRepository>> iterator() {
|
||||
final Iterator<GHRepository[]> pager = root.retrievePaged("/users/" + login + "/repos?per_page="+pageSize,GHRepository[].class,false, V3);
|
||||
|
||||
return new Iterator<List<GHRepository>>() {
|
||||
public boolean hasNext() {
|
||||
return pager.hasNext();
|
||||
}
|
||||
|
||||
public List<GHRepository> next() {
|
||||
GHRepository[] batch = pager.next();
|
||||
for (GHRepository r : batch)
|
||||
r.root = root;
|
||||
return Arrays.asList(batch);
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
@@ -58,11 +95,26 @@ public abstract class GHPerson {
|
||||
|
||||
/**
|
||||
* Gravatar ID of this user, like 0cb9832a01c22c083390f3c5dcb64105
|
||||
*
|
||||
* @deprecated
|
||||
* No longer available in the v3 API.
|
||||
*/
|
||||
public String getGravatarId() {
|
||||
return gravatar_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string like 'https://secure.gravatar.com/avatar/0cb9832a01c22c083390f3c5dcb64105'
|
||||
* that indicates the avatar image URL.
|
||||
*/
|
||||
public String getAvatarUrl() {
|
||||
if (avatar_url!=null)
|
||||
return avatar_url;
|
||||
if (gravatar_id!=null)
|
||||
return "https://secure.gravatar.com/avatar/"+gravatar_id;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the login ID of this user, like 'kohsuke'
|
||||
*/
|
||||
|
||||
@@ -25,7 +25,6 @@ package org.kohsuke.github;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* A pull request.
|
||||
@@ -64,7 +63,7 @@ public class GHPullRequest extends GHIssue {
|
||||
}
|
||||
|
||||
/**
|
||||
* The change that should be pulled.
|
||||
* The change that should be pulled. The tip of the commits to merge.
|
||||
*/
|
||||
public GHCommitPointer getHead() {
|
||||
return head;
|
||||
@@ -93,4 +92,19 @@ public class GHPullRequest extends GHIssue {
|
||||
public Date getClosedAt() {
|
||||
return GitHub.parseDate(closed_at);
|
||||
}
|
||||
|
||||
GHPullRequest wrapUp(GHRepository owner) {
|
||||
this.owner = owner;
|
||||
return wrapUp(owner.root);
|
||||
}
|
||||
|
||||
GHPullRequest wrapUp(GitHub root) {
|
||||
this.root = root;
|
||||
if (owner!=null) owner.wrap(root);
|
||||
if (issue_user!=null) issue_user.root=root;
|
||||
if (user!=null) user.root=root;
|
||||
if (base!=null) base.wrapUp(root);
|
||||
if (head!=null) head.wrapUp(root);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,12 +42,14 @@ import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import static java.util.Arrays.*;
|
||||
import static org.kohsuke.github.ApiVersion.V3;
|
||||
@@ -66,8 +68,12 @@ public class GHRepository {
|
||||
private String html_url; // this is the UI
|
||||
private GHUser owner; // not fully populated. beware.
|
||||
private boolean has_issues, has_wiki, fork, _private, has_downloads;
|
||||
private int watchers,forks,open_issues;
|
||||
private int watchers,forks,open_issues,size;
|
||||
private String created_at, pushed_at;
|
||||
private Map<Integer,GHMilestone> milestones = new HashMap<Integer, GHMilestone>();
|
||||
|
||||
private String master_branch;
|
||||
private Map<String,GHCommit> commits = new HashMap<String, GHCommit>();
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
@@ -78,12 +84,31 @@ public class GHRepository {
|
||||
}
|
||||
|
||||
/**
|
||||
* URL of this repository, like 'http://github.com/kohsuke/hudson'
|
||||
* URL of this repository, like 'http://github.com/kohsuke/jenkins'
|
||||
*/
|
||||
public String getUrl() {
|
||||
return html_url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the git:// URL to this repository, such as "git://github.com/kohsuke/jenkins.git"
|
||||
* This URL is read-only.
|
||||
*/
|
||||
public String getGitTransportUrl() {
|
||||
return "git://github.com/"+getOwnerName()+"/"+name+".git";
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the HTTPS URL to this repository, such as "https://github.com/kohsuke/jenkins.git"
|
||||
* This URL is read-only.
|
||||
*/
|
||||
public String gitHttpTransportUrl() {
|
||||
return "https://github.com/"+getOwnerName()+"/"+name+".git";
|
||||
}
|
||||
|
||||
/**
|
||||
* Short repository name without the owner. For example 'jenkins' in case of http://github.com/jenkinsci/jenkins
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
@@ -132,6 +157,11 @@ public class GHRepository {
|
||||
return open_issues;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
* null if the repository was never pushed at.
|
||||
*/
|
||||
public Date getPushedAt() {
|
||||
return GitHub.parseDate(pushed_at);
|
||||
}
|
||||
@@ -140,6 +170,19 @@ public class GHRepository {
|
||||
return GitHub.parseDate(created_at);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the primary branch you'll configure in the "Admin > Options" config page.
|
||||
*
|
||||
* @return
|
||||
* This field is null until the user explicitly configures the master branch.
|
||||
*/
|
||||
public String getMasterBranch() {
|
||||
return master_branch;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the collaborators on this repository.
|
||||
@@ -229,7 +272,7 @@ public class GHRepository {
|
||||
String url = "/repos/delete/" + owner.login +"/"+name;
|
||||
|
||||
DeleteToken token = poster.to(url, DeleteToken.class);
|
||||
poster.with("delete_token",token.delete_token).to(url);
|
||||
poster.with("delete_token", token.delete_token).to(url);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -290,14 +333,17 @@ public class GHRepository {
|
||||
* Retrieves a specified pull request.
|
||||
*/
|
||||
public GHPullRequest getPullRequest(int i) throws IOException {
|
||||
return root.retrieveWithAuth("/pulls/" + owner.login + '/' + name + "/" + i, JsonPullRequest.class).wrap(this);
|
||||
return root.retrieveWithAuth3("/repos/" + owner.login + '/' + name + "/pulls/" + i, GHPullRequest.class).wrapUp(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all the pull requests of a particular state.
|
||||
*/
|
||||
public List<GHPullRequest> getPullRequests(GHIssueState state) throws IOException {
|
||||
return root.retrieveWithAuth("/pulls/"+owner.login+'/'+name+"/"+state.name().toLowerCase(Locale.ENGLISH),JsonPullRequests.class).wrap(this);
|
||||
GHPullRequest[] r = root.retrieveWithAuth3("/repos/" + owner.login + '/' + name + "/pulls?state=" + state.name().toLowerCase(Locale.ENGLISH), GHPullRequest[].class);
|
||||
for (GHPullRequest p : r)
|
||||
p.wrapUp(this);
|
||||
return new ArrayList<GHPullRequest>(Arrays.asList(r));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -315,13 +361,58 @@ public class GHRepository {
|
||||
return root.retrieveWithAuth3(String.format("/repos/%s/%s/hooks/%d",owner.login,name,id),GHHook.class).wrap(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a commit object in this repository.
|
||||
*/
|
||||
public GHCommit getCommit(String sha1) throws IOException {
|
||||
GHCommit c = commits.get(sha1);
|
||||
if (c==null) {
|
||||
c = root.retrieve3(String.format("/repos/%s/%s/commits/%s",owner.login,name,sha1),GHCommit.class).wrapUp(this);
|
||||
commits.put(sha1,c);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists all the commits.
|
||||
*/
|
||||
public PagedIterable<GHCommit> listCommits() {
|
||||
return new PagedIterable<GHCommit>() {
|
||||
public PagedIterator<GHCommit> iterator() {
|
||||
return new PagedIterator<GHCommit>(root.retrievePaged(String.format("/repos/%s/%s/commits",owner.login,name),GHCommit[].class,false,V3)) {
|
||||
protected void wrapUp(GHCommit[] page) {
|
||||
for (GHCommit c : page)
|
||||
c.wrapUp(GHRepository.this);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists up all the commit comments in this repository.
|
||||
*/
|
||||
public PagedIterable<GHCommitComment> listCommitComments() {
|
||||
return new PagedIterable<GHCommitComment>() {
|
||||
public PagedIterator<GHCommitComment> iterator() {
|
||||
return new PagedIterator<GHCommitComment>(root.retrievePaged(String.format("/repos/%s/%s/comments",owner.login,name),GHCommitComment[].class,false,V3)) {
|
||||
@Override
|
||||
protected void wrapUp(GHCommitComment[] page) {
|
||||
for (GHCommitComment c : page)
|
||||
c.wrap(GHRepository.this);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* See https://api.github.com/hooks for possible names and their configuration scheme.
|
||||
* TODO: produce type-safe binding
|
||||
*
|
||||
* @param name
|
||||
* Type of the hook to be created.
|
||||
* Type of the hook to be created. See https://api.github.com/hooks for possible names.
|
||||
* @param config
|
||||
* The configuration hash.
|
||||
* @param events
|
||||
@@ -436,6 +527,46 @@ public class GHRepository {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets branches by {@linkplain GHBranch#getName() their names}.
|
||||
*/
|
||||
public Map<String,GHBranch> getBranches() throws IOException {
|
||||
Map<String,GHBranch> r = new TreeMap<String,GHBranch>();
|
||||
for (GHBranch p : root.retrieve3("/repos/"+owner.login+"/"+name+"/branches", GHBranch[].class)) {
|
||||
p.wrap(this);
|
||||
r.put(p.getName(),p);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
public Map<Integer, GHMilestone> getMilestones() throws IOException {
|
||||
Map<Integer,GHMilestone> milestones = new TreeMap<Integer, GHMilestone>();
|
||||
GHMilestone[] ms = root.retrieve3("/repos/"+owner.login+"/"+name+"/milestones", GHMilestone[].class);
|
||||
for (GHMilestone m : ms) {
|
||||
m.owner = this;
|
||||
m.root = root;
|
||||
milestones.put(m.getNumber(), m);
|
||||
}
|
||||
return milestones;
|
||||
}
|
||||
|
||||
public GHMilestone getMilestone(int number) throws IOException {
|
||||
GHMilestone m = milestones.get(number);
|
||||
if (m == null) {
|
||||
m = root.retrieve3("/repos/"+owner.login+"/"+name+"/milestones/"+number, GHMilestone.class);
|
||||
m.owner = this;
|
||||
m.root = root;
|
||||
milestones.put(m.getNumber(), m);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
public GHMilestone createMilestone(String title, String description) throws IOException {
|
||||
return new Poster(root,V3).withCredential()
|
||||
.with("title", title).with("description", description)
|
||||
.to("/repos/"+owner.login+"/"+name+"/milestones", GHMilestone.class,"POST").wrap(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Repository:"+owner.login+":"+name;
|
||||
|
||||
@@ -23,14 +23,10 @@
|
||||
*/
|
||||
package org.kohsuke.github;
|
||||
|
||||
import com.gargoylesoftware.htmlunit.WebClient;
|
||||
import com.gargoylesoftware.htmlunit.html.HtmlForm;
|
||||
import com.gargoylesoftware.htmlunit.html.HtmlPage;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.codehaus.jackson.map.DeserializationConfig.Feature;
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
import org.codehaus.jackson.map.introspect.VisibilityChecker.Std;
|
||||
import sun.misc.BASE64Encoder;
|
||||
import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.ANY;
|
||||
import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.NONE;
|
||||
import static org.kohsuke.github.ApiVersion.V2;
|
||||
import static org.kohsuke.github.ApiVersion.V3;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
@@ -39,18 +35,35 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.io.Reader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Properties;
|
||||
import java.util.TimeZone;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.*;
|
||||
import static org.kohsuke.github.ApiVersion.*;
|
||||
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.codehaus.jackson.JsonParseException;
|
||||
import org.codehaus.jackson.map.DeserializationConfig.Feature;
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
import org.codehaus.jackson.map.introspect.VisibilityChecker.Std;
|
||||
|
||||
import sun.misc.BASE64Encoder;
|
||||
|
||||
import com.gargoylesoftware.htmlunit.WebClient;
|
||||
import com.gargoylesoftware.htmlunit.html.HtmlForm;
|
||||
import com.gargoylesoftware.htmlunit.html.HtmlPage;
|
||||
|
||||
/**
|
||||
* Root of the GitHub API.
|
||||
@@ -66,9 +79,16 @@ public class GitHub {
|
||||
private final Map<String,GHUser> users = new HashMap<String, GHUser>();
|
||||
private final Map<String,GHOrganization> orgs = new HashMap<String, GHOrganization>();
|
||||
/*package*/ String oauthAccessToken;
|
||||
|
||||
private final String githubServer;
|
||||
|
||||
private GitHub(String login, String apiToken, String password) {
|
||||
this.login = login;
|
||||
private GitHub(String login, String apiToken, String password) {
|
||||
this ("github.com", login, apiToken, password);
|
||||
}
|
||||
|
||||
private GitHub(String githubServer, String login, String apiToken, String password) {
|
||||
this.githubServer = githubServer;
|
||||
this.login = login;
|
||||
this.apiToken = apiToken;
|
||||
this.password = password;
|
||||
|
||||
@@ -80,8 +100,9 @@ public class GitHub {
|
||||
encodedAuthorization = null;
|
||||
}
|
||||
|
||||
private GitHub (String oauthAccessToken) throws IOException {
|
||||
private GitHub (String githubServer, String oauthAccessToken) throws IOException {
|
||||
|
||||
this.githubServer = githubServer;
|
||||
this.password = null;
|
||||
this.encodedAuthorization = null;
|
||||
|
||||
@@ -115,7 +136,11 @@ public class GitHub {
|
||||
}
|
||||
|
||||
public static GitHub connectUsingOAuth (String accessToken) throws IOException {
|
||||
return new GitHub(accessToken);
|
||||
return connectUsingOAuth("github.com", accessToken);
|
||||
}
|
||||
|
||||
public static GitHub connectUsingOAuth (String githubServer, String accessToken) throws IOException {
|
||||
return new GitHub(githubServer, accessToken);
|
||||
}
|
||||
/**
|
||||
* Connects to GitHub anonymously.
|
||||
@@ -137,7 +162,7 @@ public class GitHub {
|
||||
tailApiUrl = tailApiUrl + (tailApiUrl.indexOf('?')>=0 ?'&':'?') + "access_token=" + oauthAccessToken;
|
||||
}
|
||||
|
||||
return new URL(v.url+tailApiUrl);
|
||||
return new URL(v.getApiVersionBaseUrl(githubServer)+tailApiUrl);
|
||||
}
|
||||
|
||||
/*package*/ <T> T retrieve(String tailApiUrl, Class<T> type) throws IOException {
|
||||
@@ -149,7 +174,7 @@ public class GitHub {
|
||||
}
|
||||
|
||||
/*package*/ <T> T retrieveWithAuth(String tailApiUrl, Class<T> type) throws IOException {
|
||||
return retrieveWithAuth(tailApiUrl,type,"GET");
|
||||
return retrieveWithAuth(tailApiUrl, type, "GET");
|
||||
}
|
||||
|
||||
/*package*/ <T> T retrieveWithAuth3(String tailApiUrl, Class<T> type) throws IOException {
|
||||
@@ -166,32 +191,141 @@ public class GitHub {
|
||||
|
||||
private <T> T _retrieve(String tailApiUrl, Class<T> type, String method, boolean withAuth, ApiVersion v) throws IOException {
|
||||
while (true) {// loop while API rate limit is hit
|
||||
|
||||
HttpURLConnection uc = (HttpURLConnection) getApiURL(v,tailApiUrl).openConnection();
|
||||
|
||||
if (withAuth && this.oauthAccessToken == null)
|
||||
uc.setRequestProperty("Authorization", "Basic " + encodedAuthorization);
|
||||
|
||||
uc.setRequestMethod(method);
|
||||
if (method.equals("PUT")) {
|
||||
uc.setDoOutput(true);
|
||||
uc.setRequestProperty("Content-Length","0");
|
||||
uc.getOutputStream().close();
|
||||
}
|
||||
|
||||
HttpURLConnection uc = setupConnection(method, withAuth, getApiURL(v, tailApiUrl));
|
||||
try {
|
||||
InputStreamReader r = new InputStreamReader(uc.getInputStream(), "UTF-8");
|
||||
if (type==null) {
|
||||
String data = IOUtils.toString(r);
|
||||
return null;
|
||||
}
|
||||
return MAPPER.readValue(r,type);
|
||||
return parse(uc,type);
|
||||
} catch (IOException e) {
|
||||
handleApiError(e,uc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads pagenated resources.
|
||||
*
|
||||
* Every iterator call reports a new batch.
|
||||
*/
|
||||
/*package*/ <T> Iterator<T> retrievePaged(final String tailApiUrl, final Class<T> type, final boolean withAuth, final ApiVersion v) {
|
||||
return new Iterator<T>() {
|
||||
/**
|
||||
* The next batch to be returned from {@link #next()}.
|
||||
*/
|
||||
T next;
|
||||
/**
|
||||
* URL of the next resource to be retrieved, or null if no more data is available.
|
||||
*/
|
||||
URL url;
|
||||
|
||||
{
|
||||
try {
|
||||
url = getApiURL(v, tailApiUrl);
|
||||
} catch (IOException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
fetch();
|
||||
return next!=null;
|
||||
}
|
||||
|
||||
public T next() {
|
||||
fetch();
|
||||
T r = next;
|
||||
if (r==null) throw new NoSuchElementException();
|
||||
next = null;
|
||||
return r;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
private void fetch() {
|
||||
if (next!=null) return; // already fetched
|
||||
if (url==null) return; // no more data to fetch
|
||||
|
||||
try {
|
||||
while (true) {// loop while API rate limit is hit
|
||||
HttpURLConnection uc = setupConnection("GET", withAuth, url);
|
||||
try {
|
||||
next = parse(uc,type);
|
||||
assert next!=null;
|
||||
findNextURL(uc);
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
handleApiError(e,uc);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Locate the next page from the pagination "Link" tag.
|
||||
*/
|
||||
private void findNextURL(HttpURLConnection uc) throws MalformedURLException {
|
||||
url = null; // start defensively
|
||||
String link = uc.getHeaderField("Link");
|
||||
if (link==null) return;
|
||||
|
||||
for (String token : link.split(", ")) {
|
||||
if (token.endsWith("rel=\"next\"")) {
|
||||
// found the next page. This should look something like
|
||||
// <https://api.github.com/repos?page=3&per_page=100>; rel="next"
|
||||
int idx = token.indexOf('>');
|
||||
url = new URL(token.substring(1,idx));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// no more "next" link. we are done.
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private HttpURLConnection setupConnection(String method, boolean withAuth, URL url) throws IOException {
|
||||
HttpURLConnection uc = (HttpURLConnection) url.openConnection();
|
||||
|
||||
if (withAuth && this.oauthAccessToken == null)
|
||||
uc.setRequestProperty("Authorization", "Basic " + encodedAuthorization);
|
||||
|
||||
uc.setRequestMethod(method);
|
||||
if (method.equals("PUT")) {
|
||||
uc.setDoOutput(true);
|
||||
uc.setRequestProperty("Content-Length","0");
|
||||
uc.getOutputStream().close();
|
||||
}
|
||||
uc.setRequestProperty("Accept-Encoding", "gzip");
|
||||
return uc;
|
||||
}
|
||||
|
||||
private <T> T parse(HttpURLConnection uc, Class<T> type) throws IOException {
|
||||
InputStreamReader r = null;
|
||||
try {
|
||||
r = new InputStreamReader(wrapStream(uc, uc.getInputStream()), "UTF-8");
|
||||
if (type==null) {
|
||||
String data = IOUtils.toString(r);
|
||||
return null;
|
||||
}
|
||||
return MAPPER.readValue(r,type);
|
||||
} finally {
|
||||
IOUtils.closeQuietly(r);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the "Content-Encoding" header.
|
||||
*/
|
||||
private InputStream wrapStream(HttpURLConnection uc, InputStream in) throws IOException {
|
||||
String encoding = uc.getContentEncoding();
|
||||
if (encoding==null || in==null) return in;
|
||||
if (encoding.equals("gzip")) return new GZIPInputStream(in);
|
||||
|
||||
throw new UnsupportedOperationException("Unexpected Content-Encoding: "+encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the error is because of the API limit, wait 10 sec and return normally.
|
||||
* Otherwise throw an exception reporting an error.
|
||||
@@ -210,29 +344,30 @@ public class GitHub {
|
||||
if (e instanceof FileNotFoundException)
|
||||
throw e; // pass through 404 Not Found to allow the caller to handle it intelligently
|
||||
|
||||
InputStream es = uc.getErrorStream();
|
||||
if (es!=null)
|
||||
throw (IOException)new IOException(IOUtils.toString(es,"UTF-8")).initCause(e);
|
||||
else
|
||||
throw e;
|
||||
InputStream es = wrapStream(uc, uc.getErrorStream());
|
||||
try {
|
||||
if (es!=null)
|
||||
throw (IOException)new IOException(IOUtils.toString(es,"UTF-8")).initCause(e);
|
||||
else
|
||||
throw e;
|
||||
} finally {
|
||||
IOUtils.closeQuietly(es);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link GHUser} that represents yourself.
|
||||
*/
|
||||
public GHUser getMyself() throws IOException {
|
||||
@WithBridgeMethods(GHUser.class)
|
||||
public GHMyself getMyself() throws IOException {
|
||||
requireCredential();
|
||||
|
||||
if (oauthAccessToken != null) {
|
||||
GHUser u = retrieveWithAuth("/user/show", JsonUser.class).user;
|
||||
|
||||
u.root = this;
|
||||
users.put(u.getLogin(), u);
|
||||
|
||||
return u;
|
||||
} else {
|
||||
return getUser(login);
|
||||
}
|
||||
GHMyself u = retrieveWithAuth3("/user", GHMyself.class);
|
||||
|
||||
u.root = this;
|
||||
users.put(u.getLogin(), u);
|
||||
|
||||
return u;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -241,17 +376,9 @@ public class GitHub {
|
||||
public GHUser getUser(String login) throws IOException {
|
||||
GHUser u = users.get(login);
|
||||
if (u == null) {
|
||||
|
||||
if (oauthAccessToken != null) {
|
||||
u = retrieve("/user/show/" + login, JsonUser.class).user;
|
||||
u.root = this;
|
||||
users.put(u.getLogin(), u);
|
||||
} else {
|
||||
u = retrieve("/user/show/" + login, JsonUser.class).user;
|
||||
u.root = this;
|
||||
users.put(login, u);
|
||||
}
|
||||
|
||||
u = retrieve3("/users/" + login, GHUser.class);
|
||||
u.root = this;
|
||||
users.put(u.getLogin(), u);
|
||||
}
|
||||
return u;
|
||||
}
|
||||
@@ -279,9 +406,42 @@ public class GitHub {
|
||||
return o;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the repository object from 'user/reponame' string that GitHub calls as "repository name"
|
||||
*
|
||||
* @see GHRepository#getName()
|
||||
*/
|
||||
public GHRepository getRepository(String name) throws IOException {
|
||||
String[] tokens = name.split("/");
|
||||
return getUser(tokens[0]).getRepository(tokens[1]);
|
||||
}
|
||||
|
||||
public Map<String, GHOrganization> getMyOrganizations() throws IOException {
|
||||
return retrieveWithAuth("/organizations",JsonOrganizations.class).wrap(this);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Public events visible to you. Equivalent of what's displayed on https://github.com/
|
||||
*/
|
||||
public List<GHEventInfo> getEvents() throws IOException {
|
||||
// TODO: pagenation
|
||||
GHEventInfo[] events = retrieve3("/events", GHEventInfo[].class);
|
||||
for (GHEventInfo e : events)
|
||||
e.wrapUp(this);
|
||||
return Arrays.asList(events);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the GitHub event object.
|
||||
*
|
||||
* This is primarily intended for receiving a POST HTTP call from a hook.
|
||||
* Unfortunately, hook script payloads aren't self-descriptive, so you need
|
||||
* to know the type of the payload you are expecting.
|
||||
*/
|
||||
public <T extends GHEventPayload> T parseEventPayload(Reader r, Class<T> type) throws IOException {
|
||||
T t = MAPPER.readValue(r, type);
|
||||
t.wrapUp(this);
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -301,7 +461,7 @@ public class GitHub {
|
||||
*/
|
||||
public boolean isCredentialValid() throws IOException {
|
||||
try {
|
||||
retrieveWithAuth("/user/show",JsonUser.class);
|
||||
retrieveWithAuth3("/user",GHUser.class);
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
@@ -329,9 +489,12 @@ public class GitHub {
|
||||
}
|
||||
|
||||
/*package*/ static Date parseDate(String timestamp) {
|
||||
if (timestamp==null) return null;
|
||||
for (String f : TIME_FORMATS) {
|
||||
try {
|
||||
return new SimpleDateFormat(f).parse(timestamp);
|
||||
SimpleDateFormat df = new SimpleDateFormat(f);
|
||||
df.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||
return df.parse(timestamp);
|
||||
} catch (ParseException e) {
|
||||
// try next
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010, Kohsuke Kawaguchi
|
||||
* Copyright (c) 2011, Eric Maupin
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -21,11 +21,16 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.kohsuke.github;
|
||||
|
||||
/**
|
||||
* @author Kohsuke Kawaguchi
|
||||
* @author Eric Maupin
|
||||
*/
|
||||
class JsonUser {
|
||||
public GHUser user;
|
||||
class JsonBranch {
|
||||
GHBranch branch;
|
||||
|
||||
GHBranch wrap(GHRepository r) {
|
||||
return branch.wrap(r);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010, Kohsuke Kawaguchi
|
||||
* Copyright (c) 2011, Eric Maupin
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -21,17 +21,20 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.kohsuke.github;
|
||||
|
||||
/**
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
class JsonPullRequest {
|
||||
public GHPullRequest pull;
|
||||
import java.util.List;
|
||||
|
||||
public GHPullRequest wrap(GHRepository owner) {
|
||||
pull.owner = owner;
|
||||
pull.root = owner.root;
|
||||
return pull;
|
||||
/**
|
||||
* @author Eric Maupin
|
||||
*/
|
||||
class JsonBranches {
|
||||
List<GHBranch> branches;
|
||||
|
||||
public List<GHBranch> wrap(GHRepository owner) {
|
||||
for (GHBranch branch : branches)
|
||||
branch.wrap(owner);
|
||||
return branches;
|
||||
}
|
||||
}
|
||||
}
|
||||
8
src/main/java/org/kohsuke/github/JsonMyself.java
Normal file
8
src/main/java/org/kohsuke/github/JsonMyself.java
Normal file
@@ -0,0 +1,8 @@
|
||||
package org.kohsuke.github;
|
||||
|
||||
/**
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
class JsonMyself {
|
||||
GHMyself user;
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010, Kohsuke Kawaguchi
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package org.kohsuke.github;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
class JsonPullRequests {
|
||||
public List<GHPullRequest> pulls;
|
||||
|
||||
public List<GHPullRequest> wrap(GHRepository owner) {
|
||||
for (GHPullRequest pull : pulls) {
|
||||
pull.owner = owner;
|
||||
pull.root = owner.root;
|
||||
}
|
||||
return pulls;
|
||||
}
|
||||
}
|
||||
8
src/main/java/org/kohsuke/github/PagedIterable.java
Normal file
8
src/main/java/org/kohsuke/github/PagedIterable.java
Normal file
@@ -0,0 +1,8 @@
|
||||
package org.kohsuke.github;
|
||||
|
||||
/**
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public interface PagedIterable<T> extends Iterable<T> {
|
||||
PagedIterator<T> iterator();
|
||||
}
|
||||
64
src/main/java/org/kohsuke/github/PagedIterator.java
Normal file
64
src/main/java/org/kohsuke/github/PagedIterator.java
Normal file
@@ -0,0 +1,64 @@
|
||||
package org.kohsuke.github;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Iterator over a pagenated data source.
|
||||
*
|
||||
* Aside from the normal iterator operation, this method exposes {@link #nextPage()}
|
||||
* that allows the caller to retrieve items per page.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public abstract class PagedIterator<T> implements Iterator<T> {
|
||||
private final Iterator<T[]> base;
|
||||
|
||||
/**
|
||||
* Current batch that we retrieved but haven't returned to the caller.
|
||||
*/
|
||||
private T[] current;
|
||||
private int pos;
|
||||
|
||||
/*package*/ PagedIterator(Iterator<T[]> base) {
|
||||
this.base = base;
|
||||
}
|
||||
|
||||
protected abstract void wrapUp(T[] page);
|
||||
|
||||
public boolean hasNext() {
|
||||
return (current!=null && pos<current.length) || base.hasNext();
|
||||
}
|
||||
|
||||
public T next() {
|
||||
fetch();
|
||||
|
||||
return current[pos++];
|
||||
}
|
||||
|
||||
private void fetch() {
|
||||
while (current==null || current.length<=pos) {
|
||||
current = base.next();
|
||||
wrapUp(current);
|
||||
pos = 0;
|
||||
}
|
||||
// invariant at the end: there's some data to retrieve
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next page worth of data.
|
||||
*/
|
||||
public List<T> nextPage() {
|
||||
fetch();
|
||||
List<T> r = Arrays.asList(current);
|
||||
r = r.subList(pos,r.size());
|
||||
current = null;
|
||||
pos = 0;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
@@ -33,7 +33,9 @@ import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Reader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.ProtocolException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -86,6 +88,12 @@ class Poster {
|
||||
return _with(key, value);
|
||||
}
|
||||
|
||||
public Poster with(String key, Integer value) {
|
||||
if (value!=null)
|
||||
_with(key, value.intValue());
|
||||
return this;
|
||||
}
|
||||
|
||||
public Poster with(String key, boolean value) {
|
||||
return _with(key, value);
|
||||
}
|
||||
@@ -136,7 +144,18 @@ class Poster {
|
||||
uc.setRequestProperty("Authorization", "Basic " + root.encodedAuthorization);
|
||||
}
|
||||
}
|
||||
uc.setRequestMethod(method);
|
||||
try {
|
||||
uc.setRequestMethod(method);
|
||||
} catch (ProtocolException e) {
|
||||
// JDK only allows one of the fixed set of verbs. Try to override that
|
||||
try {
|
||||
Field $method = HttpURLConnection.class.getDeclaredField("method");
|
||||
$method.setAccessible(true);
|
||||
$method.set(uc,method);
|
||||
} catch (Exception x) {
|
||||
throw (IOException)new IOException("Failed to set the custom verb").initCause(x);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (v==ApiVersion.V2) {
|
||||
|
||||
@@ -1,16 +1,31 @@
|
||||
package org.kohsuke;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.kohsuke.github.GHCommit;
|
||||
import org.kohsuke.github.GHCommit.File;
|
||||
import org.kohsuke.github.GHCommitComment;
|
||||
import org.kohsuke.github.GHEvent;
|
||||
import org.kohsuke.github.GHEventInfo;
|
||||
import org.kohsuke.github.GHEventPayload;
|
||||
import org.kohsuke.github.GHHook;
|
||||
import org.kohsuke.github.GHBranch;
|
||||
import org.kohsuke.github.GHIssueState;
|
||||
import org.kohsuke.github.GHKey;
|
||||
import org.kohsuke.github.GHMyself;
|
||||
import org.kohsuke.github.GHOrganization;
|
||||
import org.kohsuke.github.GHOrganization.Permission;
|
||||
import org.kohsuke.github.GHRepository;
|
||||
import org.kohsuke.github.GHTeam;
|
||||
import org.kohsuke.github.GHUser;
|
||||
import org.kohsuke.github.GitHub;
|
||||
import org.kohsuke.github.PagedIterable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Unit test for simple App.
|
||||
@@ -21,6 +36,33 @@ public class AppTest extends TestCase {
|
||||
assertFalse(GitHub.connect("totally","bogus").isCredentialValid());
|
||||
}
|
||||
|
||||
public void testFetchPullRequest() throws Exception {
|
||||
GitHub gh = GitHub.connect();
|
||||
GHRepository r = gh.getOrganization("jenkinsci").getRepository("jenkins");
|
||||
assertEquals("master",r.getMasterBranch());
|
||||
r.getPullRequest(1);
|
||||
r.getPullRequests(GHIssueState.OPEN);
|
||||
}
|
||||
|
||||
public void tryGetMyself() throws Exception {
|
||||
GitHub hub = GitHub.connect();
|
||||
GHMyself me = hub.getMyself();
|
||||
System.out.println(me);
|
||||
GHUser u = hub.getUser("kohsuke2");
|
||||
System.out.println(u);
|
||||
for (List<GHRepository> lst : me.iterateRepositories(100)) {
|
||||
for (GHRepository r : lst) {
|
||||
System.out.println(r.getPushedAt());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testPublicKeys() throws Exception {
|
||||
GitHub gh = GitHub.connect();
|
||||
List<GHKey> keys = gh.getMyself().getPublicKeys();
|
||||
System.out.println(keys);
|
||||
}
|
||||
|
||||
public void tryOrgFork() throws Exception {
|
||||
GitHub gh = GitHub.connect();
|
||||
gh.getUser("kohsuke").getRepository("rubywm").forkTo(gh.getOrganization("jenkinsci"));
|
||||
@@ -44,6 +86,58 @@ public class AppTest extends TestCase {
|
||||
System.out.println(o);
|
||||
}
|
||||
|
||||
public void testCommit() throws Exception {
|
||||
GitHub gitHub = GitHub.connect();
|
||||
GHCommit commit = gitHub.getUser("jenkinsci").getRepository("jenkins").getCommit("08c1c9970af4d609ae754fbe803e06186e3206f7");
|
||||
System.out.println(commit);
|
||||
assertEquals(1, commit.getParents().size());
|
||||
assertEquals(1,commit.getFiles().size());
|
||||
|
||||
File f = commit.getFiles().get(0);
|
||||
assertEquals(48,f.getLinesChanged());
|
||||
assertEquals("modified",f.getStatus());
|
||||
assertEquals("changelog.html",f.getFileName());
|
||||
}
|
||||
|
||||
public void testListCommits() throws Exception {
|
||||
GitHub gitHub = GitHub.connect();
|
||||
List<String> sha1 = new ArrayList<String>();
|
||||
for (GHCommit c : gitHub.getUser("kohsuke").getRepository("empty-commit").listCommits()) {
|
||||
System.out.println(c.getSHA1());
|
||||
sha1.add(c.getSHA1());
|
||||
}
|
||||
assertEquals("fdfad6be4db6f96faea1f153fb447b479a7a9cb7",sha1.get(0));
|
||||
assertEquals(1,sha1.size());
|
||||
}
|
||||
|
||||
public void testBranches() throws Exception {
|
||||
GitHub gitHub = GitHub.connect();
|
||||
Map<String,GHBranch> b =
|
||||
gitHub.getUser("jenkinsci").getRepository("jenkins").getBranches();
|
||||
System.out.println(b);
|
||||
}
|
||||
|
||||
public void testCommitComment() throws Exception {
|
||||
GitHub gitHub = GitHub.connect();
|
||||
GHRepository r = gitHub.getUser("jenkinsci").getRepository("jenkins");
|
||||
PagedIterable<GHCommitComment> comments = r.listCommitComments();
|
||||
List<GHCommitComment> batch = comments.iterator().nextPage();
|
||||
for (GHCommitComment comment : batch) {
|
||||
System.out.println(comment.getBody());
|
||||
assertSame(comment.getOwner(), r);
|
||||
}
|
||||
}
|
||||
|
||||
public void tryCreateCommitComment() throws Exception {
|
||||
GitHub gitHub = GitHub.connect();
|
||||
GHCommit commit = gitHub.getUser("kohsuke").getRepository("sandbox-ant").getCommit("8ae38db0ea5837313ab5f39d43a6f73de3bd9000");
|
||||
GHCommitComment c = commit.createComment("[testing](http://kohsuse.org/)");
|
||||
System.out.println(c);
|
||||
c.update("updated text");
|
||||
System.out.println(c);
|
||||
c.delete();
|
||||
}
|
||||
|
||||
public void tryHook() throws Exception {
|
||||
GitHub gitHub = GitHub.connect();
|
||||
GHRepository r = gitHub.getMyself().getRepository("test2");
|
||||
@@ -53,9 +147,22 @@ public class AppTest extends TestCase {
|
||||
for (GHHook h : r.getHooks())
|
||||
h.delete();
|
||||
}
|
||||
|
||||
public void testEventApi() throws Exception {
|
||||
GitHub gitHub = GitHub.connect();
|
||||
for (GHEventInfo ev : gitHub.getEvents()) {
|
||||
System.out.println(ev);
|
||||
if (ev.getType()==GHEvent.PULL_REQUEST) {
|
||||
GHEventPayload.PullRequest pr = ev.getPayload(GHEventPayload.PullRequest.class);
|
||||
System.out.println(pr.getNumber());
|
||||
System.out.println(pr.getPullRequest());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testApp() throws IOException {
|
||||
GitHub gitHub = GitHub.connect();
|
||||
System.out.println(gitHub.getMyself().getEmails());
|
||||
|
||||
// GHRepository r = gitHub.connect().getOrganization("jenkinsci").createRepository("kktest4", "Kohsuke's test", "http://kohsuke.org/", "Everyone", true);
|
||||
// r.fork();
|
||||
@@ -147,6 +254,15 @@ public class AppTest extends TestCase {
|
||||
System.out.println(hooks);
|
||||
}
|
||||
|
||||
public void testOrgRepositories() throws IOException {
|
||||
GitHub gitHub = GitHub.connect();
|
||||
GHOrganization j = gitHub.getOrganization("jenkinsci");
|
||||
long start = System.currentTimeMillis();
|
||||
Map<String, GHRepository> repos = j.getRepositories();
|
||||
long end = System.currentTimeMillis();
|
||||
System.out.printf("%d repositories in %dms\n",repos.size(),end-start);
|
||||
}
|
||||
|
||||
public void testOrganization() throws IOException {
|
||||
GitHub gitHub = GitHub.connect();
|
||||
GHOrganization j = gitHub.getOrganization("jenkinsci");
|
||||
|
||||
32
src/test/java/org/kohsuke/HookApp.java
Normal file
32
src/test/java/org/kohsuke/HookApp.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package org.kohsuke;
|
||||
|
||||
import org.kohsuke.github.GHEventPayload;
|
||||
import org.kohsuke.github.GitHub;
|
||||
import org.kohsuke.stapler.StaplerRequest;
|
||||
import org.kohsuke.stapler.jetty.JettyRunner;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
|
||||
/**
|
||||
* App to test the hook script. You need some internet-facing server that can forward the request to you
|
||||
* (typically via SSH reverse port forwarding.)
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
public class HookApp {
|
||||
public static void main(String[] args) throws Exception {
|
||||
// GitHub.connect().getMyself().getRepository("sandbox").createWebHook(
|
||||
// new URL("http://173.203.118.45:18080/"), EnumSet.of(GHEvent.PULL_REQUEST));
|
||||
JettyRunner jr = new JettyRunner(new HookApp());
|
||||
jr.addHttpListener(8080);
|
||||
jr.start();
|
||||
}
|
||||
|
||||
public void doIndex(StaplerRequest req) throws IOException {
|
||||
String str = req.getParameter("payload");
|
||||
System.out.println(str);
|
||||
GHEventPayload.PullRequest o = GitHub.connect().parseEventPayload(new StringReader(str),GHEventPayload.PullRequest.class);
|
||||
System.out.println(o);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user