Compare commits

...

100 Commits

Author SHA1 Message Date
Kohsuke Kawaguchi
c6fdae3b3c [maven-release-plugin] prepare release github-api-1.50 2014-03-28 10:59:47 -07:00
Kohsuke Kawaguchi
320cf0fea2 Seeing a failure to create 2014-03-28 10:58:41 -07:00
Kohsuke Kawaguchi
0261f1262f fixed a test case 2014-03-28 10:58:41 -07:00
Kohsuke Kawaguchi
5278ae3662 Merge pull request #75 from rtyley/check-team-membership
Support the check-user-team-membership API call
2014-03-28 10:24:18 -07:00
Kohsuke Kawaguchi
2941c44de2 Merge pull request #73 from rtyley/fix-issue-labels-setter
Fix GHIssue.setLabels()
2014-03-28 10:23:15 -07:00
Kohsuke Kawaguchi
627222602e Merge pull request #72 from farmdawgnation/patch-1
Un-finalize GHContent.
2014-03-28 10:23:03 -07:00
Kohsuke Kawaguchi
e13b1ffc48 looks like the 'tire' repository is gone 2014-03-28 10:11:15 -07:00
Kohsuke Kawaguchi
10bafce217 fixed a test 2014-03-28 10:08:08 -07:00
Kohsuke Kawaguchi
4817969495 fixed a broken test 2014-03-28 10:06:50 -07:00
Kohsuke Kawaguchi
2feda55eb7 looks like we need to pick another user here 2014-03-28 10:01:59 -07:00
Kohsuke Kawaguchi
a74cfd453a Added support for getting issues by milestone and state.
rework AppTest to work better for people other than kohsuke

This patch was originally from @evanchooly. Reworked to avoid whitespace
changes.
2014-03-28 09:57:04 -07:00
Kohsuke Kawaguchi
a360f65133 merging a portion of pull request #70 2014-03-28 09:49:38 -07:00
Kohsuke Kawaguchi
6a903d65a7 Fixed a bug in the databinding of the 'private' field.
Luca pointed out this bug in
ae7a616e92
2014-03-28 09:47:27 -07:00
Kohsuke Kawaguchi
d4b3166036 Merge branch 'pull-69' 2014-03-28 09:42:00 -07:00
Kohsuke Kawaguchi
21a54e2333 The parent commit appears to be totally untested.
The placement of the method makes no sense, and the API route is wrong.
The parameter is missing, and the expected response type is wrong.
2014-03-28 09:40:55 -07:00
Kohsuke Kawaguchi
37c58bffba indentation fix 2014-03-28 09:37:11 -07:00
Kohsuke Kawaguchi
4a42b7277c Merge branch 'pull-76' 2014-03-28 09:35:43 -07:00
Kohsuke Kawaguchi
071aea397b Keep the original signature intact for backward compatibility 2014-03-28 09:35:37 -07:00
Kohsuke Kawaguchi
cd5ab1ae9b need to populate enum 2014-03-18 11:52:00 -07:00
Roberto Tyley
d29ea97948 Fix org.getMembers() to 'wrap' returned users for post-populating
This fixes an issue introduced with PR #66 in commit fee02a3d16 - the
`getMembers()` method switched to using paging, but lost the code that
populated the users with a full set of values.

This commit just applies 'wrapping' to all users returned, so that methods
like `user.getCreatedAt()` can be called on returned users without throwing
a NullPointerException - the reference to 'root' allows the user objects to
populate themselves.
2014-03-14 09:22:15 +00:00
Roberto Tyley
9930e7bb93 Add org public-members call, to complement the full members list
http://developer.github.com/v3/orgs/members/#public-members-list
2014-03-13 22:04:45 +00:00
Roberto Tyley
b1d37e4848 Support the check-user-team-membership API call
http://developer.github.com/v3/orgs/teams/#get-team-member
2014-03-12 21:46:14 +00:00
Roberto Tyley
893152cdf3 Fix GHIssue.setLabels() - *don't* set 'assignee' instead! 2014-03-08 16:05:33 +00:00
Matt Farmer
efbf98751d Un-finalize GHContent.
GHContent was declared as a final class, which makes it impossible to mock with libraries like Mockito.
2014-03-07 22:14:21 -05:00
Luca Milanesio
caac294e79 BugFix when listing repositories of a GitHub Organisation
Repositories of a GitHub Organisation are under 
/orgs/:org/repos as documented at:
http://developer.github.com/v3/repos/#list-organization-repositories

We need then to override the GHPerson implementation
which would have just returned the user's repositories.
2014-02-28 17:45:36 +00:00
vanjikumaran
d145ad8f47 Created new method to automate the merge 2014-02-24 17:00:11 +05:30
lindseydew
628034ae8c add a filter param to the get members method 2014-02-11 18:07:01 +00:00
Ryan Kennedy
fee02a3d16 Support paging when fetching organization members
Organization members are a paged list in the V3 GitHub API. Previously the code would fetch only the first page of ~30 members and return that. This change switches the return to a PagedIterable<GHUser> so clients can fetch the entire organization's member list.
2014-01-22 09:56:06 -08:00
Kohsuke Kawaguchi
ce5ae13bf6 [maven-release-plugin] prepare for next development iteration 2014-01-06 08:56:38 -08:00
Kohsuke Kawaguchi
26b6a94e32 [maven-release-plugin] prepare release github-api-1.49 2014-01-06 08:56:34 -08:00
Kohsuke Kawaguchi
be6ef475ba [maven-release-plugin] prepare for next development iteration 2014-01-06 08:52:00 -08:00
Kohsuke Kawaguchi
55e218ac37 [maven-release-plugin] prepare release github-api-1.48 2014-01-06 08:51:56 -08:00
Kohsuke Kawaguchi
7d1f636cdd Recover from earlier test failures 2014-01-01 21:12:17 -08:00
Kohsuke Kawaguchi
a4b8b9b09b Merge pull request #61 from lucamilanesio/master
Fetching of user's verified keys through standard OAuth scope.
2014-01-01 15:26:58 -08:00
Kohsuke Kawaguchi
4e8e28d27c Merge pull request #59 from farmdawgnation/contents-api
Contents API
2014-01-01 15:26:23 -08:00
Luca Milanesio
4b52414435 Fetching of user's verified keys through standard OAuth scope.
Allow the fetching of a user's verified key list without
requiring to have an OAuth user scope (which implies
user's profile READ/WRITE permissions).
This would relax the requirements of GitHub OAuth scope
when fetching public information such as their SSH
public keys.
2013-12-11 00:30:27 +00:00
Matt Farmer
811b96bcbe Implement the ability to retrieve content from a particular ref. 2013-11-28 10:02:37 -05:00
Matt Farmer
f3207855ca Implement a CRUD integration test for the content api. 2013-11-28 09:45:54 -05:00
Matt Farmer
9f3c5b93e3 Store encoded content in class level variable on update. 2013-11-28 09:45:21 -05:00
Matt Farmer
a56357f0c1 Implement the ability to retrieve conent if not populated.
The create and update API calls don't send back the content you just
sent, so that field is null. If this GHContent was instantiated from one
of those calls, we want to make sure we can retrieve the content (and
updated sha, etc) on the fly.
2013-11-28 09:44:27 -05:00
Matt Farmer
f8d14d2e56 Implement the ability to delete content. 2013-11-28 00:37:40 -05:00
Matt Farmer
b0c30759c8 Properly wrap content on directory listing retrieval. 2013-11-28 00:33:07 -05:00
Matt Farmer
54037e6e10 Add the ability to specify a branch name with GHContent updates. 2013-11-28 00:29:49 -05:00
Matt Farmer
fc260d4a37 Implement the ability to create content via content api. 2013-11-28 00:21:25 -05:00
Matt Farmer
387d4e5bc9 Return the new GHContentUpdateResponse from content changes. 2013-11-28 00:12:30 -05:00
Matt Farmer
4ffd46b391 Implement the ability to update existing content. 2013-11-28 00:03:43 -05:00
Matt Farmer
3b49370c06 Add the ability to retrieve the sha of the content. 2013-11-27 23:28:40 -05:00
Alexandre COLLIGNON
925d26e54c Add GitHub Contents API read methods 2013-11-27 22:35:41 -05:00
Kohsuke Kawaguchi
1283006b53 [maven-release-plugin] prepare for next development iteration 2013-11-27 11:57:40 -08:00
Kohsuke Kawaguchi
83a718c9db [maven-release-plugin] prepare release github-api-1.47 2013-11-27 11:57:35 -08:00
Kohsuke Kawaguchi
2abf03ccb7 Minor doc improvement 2013-11-27 11:52:47 -08:00
Kohsuke Kawaguchi
a59810a487 Merge pull request #56 from endeavor85/master
Use `PagedIterator<GHIssue>` to retrieve repository issues
2013-11-27 11:49:44 -08:00
Kohsuke Kawaguchi
9cc9e06ad1 Merge pull request #58 from rtholmes/master
Add support for PULL_REQUEST_REVIEW_COMMENT event types.
2013-11-27 11:49:17 -08:00
reid holmes
0108a0c146 Add support for PULL_REQUEST_REVIEW_COMMENT event types. 2013-11-26 15:13:36 -05:00
endeavor85
4188758d84 Use PagedIterator<GHIssue> to retrieve repository issues. Overcomes
default 30 item page size limit.
2013-11-24 02:54:18 -06:00
Kohsuke Kawaguchi
2144100f81 [maven-release-plugin] prepare for next development iteration 2013-11-13 13:05:29 -08:00
Kohsuke Kawaguchi
8a61e04be6 [maven-release-plugin] prepare release github-api-1.46 2013-11-13 13:05:24 -08:00
Kohsuke Kawaguchi
eaeb083891 Perhaps this will help resolve? 2013-11-12 13:13:18 -08:00
Kohsuke Kawaguchi
25e117b412 oops 2013-11-12 12:47:37 -08:00
Kohsuke Kawaguchi
6b7ceed1a5 Short cut 2013-11-12 12:45:39 -08:00
Kohsuke Kawaguchi
0533fc98a2 bumped up to a newer version 2013-11-12 12:21:17 -08:00
Kohsuke Kawaguchi
edde3ab2fb added one more field based on observations 2013-11-12 12:17:57 -08:00
Kohsuke Kawaguchi
ec20e518be adding a new payload implementation for PushEvent 2013-11-12 12:14:34 -08:00
Kohsuke Kawaguchi
930a582afa Unified various different instances of the "author" class 2013-11-12 12:10:33 -08:00
Kohsuke Kawaguchi
7536eeea54 V2 code no longer needed 2013-11-12 12:01:49 -08:00
Kohsuke Kawaguchi
d940d43907 added more event support 2013-11-12 11:52:40 -08:00
Kohsuke Kawaguchi
3ad3dd9493 [maven-release-plugin] prepare for next development iteration 2013-11-09 15:19:27 -08:00
Kohsuke Kawaguchi
553df7ac85 [maven-release-plugin] prepare release github-api-1.45 2013-11-09 15:19:23 -08:00
Kohsuke Kawaguchi
9648602252 Merge branch 'pull-51' 2013-11-09 15:17:21 -08:00
Kohsuke Kawaguchi
63d0d13330 Better and more secure to use OAuth. 2013-11-09 15:17:01 -08:00
Kohsuke Kawaguchi
ff9b538a49 doc touch up 2013-11-09 15:11:02 -08:00
Kohsuke Kawaguchi
6632da34c0 this dependency is for testing 2013-11-09 15:08:07 -08:00
evanchooly
178c9ff4d0 add support (most of) the release-related endpoints 2013-11-04 20:08:24 -05:00
Kohsuke Kawaguchi
bfefeae5c1 Merged pull request #45 with some changes 2013-11-02 18:15:31 -07:00
Kohsuke Kawaguchi
ebf953cbc4 Massaging the pull request.
- GHPerson really should be an abstract class
- static listPullRequests method does not fit the design of this
  library, although I'm very sympathetic as to why Luca wanted to do it.
  Nonetheless I'm removing this in favor of the lazy loading of the
  state to avoid unnecessary calls in the future.
2013-11-02 18:13:40 -07:00
Luca Milanesio
19ec3321ae Gets commit details of a pull request.
Retrieves the list of commits included in the pull request.
Commit object returned is not a full GHCommit and includes
just a small subset of information.
2013-10-09 16:59:18 +01:00
Kohsuke Kawaguchi
d82af9f1a0 Merge pull request #50 from pescuma/jackson
Updates Jackson to 2.2.3
2013-10-02 08:31:42 -07:00
Ricardo Pescuma Domenecci
4712d2c8ac Using version 2 of jackson 2013-09-28 14:25:23 -03:00
Ricardo Pescuma Domenecci
a2df4217fd Updated issue label with ifts fields 2013-09-28 12:43:01 -03:00
Luca Milanesio
096c96550b Allows fetching pull requests by knowing repo-name and owner. 2013-09-27 09:18:22 +01:00
Luca Milanesio
2fb3f31930 GHRepository owner is NOT a GHUser but more generically a GHPerson.
When GitHub repositories are associated to organisations,
the owner is NOT the user but the org itself.
2013-09-27 09:12:54 +01:00
Luca Milanesio
f52b4a2e11 Allows to define page size for repository lists.
Extension of the listRepositories() with the desired
pageSize. This allows to reduce the number of calls
to GitHub API for fetching the entire set of repositories
browsing all the pages.

Additionally allows to match the UX paging with the
underlying GitHub API paging, increasing performance
and reducing hourly API allowance.
2013-09-16 00:41:10 +01:00
Kohsuke Kawaguchi
bbc78ffec6 [maven-release-plugin] prepare for next development iteration 2013-09-07 13:32:24 +01:00
Kohsuke Kawaguchi
3606f412b3 [maven-release-plugin] prepare release github-api-1.44 2013-09-07 13:32:15 +01:00
Kohsuke Kawaguchi
6e0e94094b Massaging the changes 2013-09-07 13:29:23 +01:00
Kohsuke Kawaguchi
976960f495 Merge pull request #42 from paulbutenko/master
Commit's short info model
2013-09-07 05:25:58 -07:00
Kohsuke Kawaguchi
d2f2f3b2d3 Merge pull request #44 from stephenc/is-anonymous
Provide a way to determine if the connection is anonymous
2013-09-07 05:18:29 -07:00
Kohsuke Kawaguchi
2da7c45840 Merge pull request #43 from stephenc/master
GHMyself should allow accessing the private repos and orgs too
2013-09-07 05:18:00 -07:00
Stephen Connolly
fb078de627 Provide a way to determine if the connection is anonymous 2013-08-29 14:33:04 +01:00
Stephen Connolly
da46b7fddb GHMyself should allow accessing the private repos and orgs too 2013-08-29 14:29:58 +01:00
Paul Butenko
c4e0729b7d GHCOmpare reverted, getCommit changed to getCommitShortInfo 2013-08-17 01:09:55 +03:00
Paul Butenko
eee9f0ace5 Original formating restored 2013-08-17 00:48:42 +03:00
Paul Butenko
d0692458a3 New model for short info of the commit was added 2013-08-17 00:41:45 +03:00
Kohsuke Kawaguchi
c96e6c7c92 [maven-release-plugin] prepare for next development iteration 2013-07-06 22:26:45 -07:00
Kohsuke Kawaguchi
4956278f17 [maven-release-plugin] prepare release github-api-1.43 2013-07-06 22:26:39 -07:00
Kohsuke Kawaguchi
5858a86624 using the latest 2013-07-06 22:24:21 -07:00
Kohsuke Kawaguchi
c87d178a6a added a method that matches the convention elsewhere. 2013-07-06 17:49:56 -07:00
Kohsuke Kawaguchi
6fc872b1fd this is no longer efficient 2013-07-06 17:49:46 -07:00
Kohsuke Kawaguchi
589c5783a0 "myself" only makes sense when there's a credential 2013-05-24 12:01:56 -07:00
Kohsuke Kawaguchi
40165628d6 [maven-release-plugin] prepare for next development iteration 2013-05-07 11:09:20 -07:00
32 changed files with 1796 additions and 131 deletions

31
pom.xml
View File

@@ -3,11 +3,11 @@
<parent>
<groupId>org.kohsuke</groupId>
<artifactId>pom</artifactId>
<version>4</version>
<version>6</version>
</parent>
<artifactId>github-api</artifactId>
<version>1.42</version>
<version>1.50</version>
<name>GitHub API for Java</name>
<url>http://github-api.kohsuke.org/</url>
<description>GitHub API for Java</description>
@@ -16,6 +16,7 @@
<connection>scm:git:git@github.com/kohsuke/${project.artifactId}.git</connection>
<developerConnection>scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git</developerConnection>
<url>http://${project.artifactId}.kohsuke.org/</url>
<tag>HEAD</tag>
</scm>
<distributionManagement>
@@ -34,7 +35,7 @@
<plugin>
<groupId>com.infradna.tool</groupId>
<artifactId>bridge-method-injector</artifactId>
<version>1.2</version>
<version>1.8</version>
<executions>
<execution>
<goals>
@@ -60,13 +61,13 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.9</version>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
@@ -76,7 +77,7 @@
<dependency>
<groupId>com.infradna.tool</groupId>
<artifactId>bridge-method-annotation</artifactId>
<version>1.4</version>
<version>1.8</version>
<optional>true</optional>
</dependency>
<dependency>
@@ -85,14 +86,25 @@
<version>1.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit</artifactId>
<version>3.1.0.201310021548-r</version>
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>repo.jenkins-ci.org</id>
<url>http://repo.jenkins-ci.org/public/</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>repo.jenkins-ci.org</id>
<url>http://repo.jenkins-ci.org/public/</url>
</pluginRepository>
</pluginRepositories>
<reporting>
<plugins>
@@ -102,4 +114,5 @@
</plugin>
</plugins>
</reporting>
</project>

View File

@@ -0,0 +1,108 @@
package org.kohsuke.github;
import java.io.IOException;
import java.util.Date;
/**
* Asset in a release.
*
* @see GHRelease#getAssets()
*/
public class GHAsset {
GitHub root;
GHRepository owner;
private String url;
private String id;
private String name;
private String label;
private String state;
private String content_type;
private long size;
private long download_count;
private Date created_at;
private Date updated_at;
public String getContentType() {
return content_type;
}
public void setContentType(String contentType) throws IOException {
edit("content_type", contentType);
this.content_type = contentType;
}
public Date getCreatedAt() {
return created_at;
}
public long getDownloadCount() {
return download_count;
}
public String getId() {
return id;
}
public String getLabel() {
return label;
}
public void setLabel(String label) throws IOException {
edit("label", label);
this.label = label;
}
public String getName() {
return name;
}
public GHRepository getOwner() {
return owner;
}
public GitHub getRoot() {
return root;
}
public long getSize() {
return size;
}
public String getState() {
return state;
}
public Date getUpdatedAt() {
return updated_at;
}
public String getUrl() {
return url;
}
private void edit(String key, Object value) throws IOException {
new Requester(root)._with(key, value).method("PATCH").to(getApiRoute());
}
public void delete() throws IOException {
new Requester(root).method("DELETE").to(getApiRoute());
}
private String getApiRoute() {
return "/repos/" + owner.getOwnerName() + "/" + owner.getName() + "/releases/assets/" + id;
}
GHAsset wrap(GHRelease release) {
this.owner = release.getOwner();
this.root = owner.root;
return this;
}
public static GHAsset[] wrap(GHAsset[] assets, GHRelease release) {
for (GHAsset aTo : assets) {
aTo.wrap(release);
}
return assets;
}
}

View File

@@ -1,5 +1,7 @@
package org.kohsuke.github;
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
import java.io.IOException;
import java.net.URL;
import java.util.AbstractList;
@@ -16,6 +18,47 @@ import java.util.List;
*/
public class GHCommit {
private GHRepository owner;
private ShortInfo commit;
/**
* Short summary of this commit.
*/
public static class ShortInfo {
private GHAuthor author;
private GHAuthor committer;
private String message;
private int comment_count;
@WithBridgeMethods(value=GHAuthor.class,castRequired=true)
public GitUser getAuthor() {
return author;
}
@WithBridgeMethods(value=GHAuthor.class,castRequired=true)
public GitUser getCommitter() {
return committer;
}
/**
* Commit message.
*/
public String getMessage() {
return message;
}
public int getCommentCount() {
return comment_count;
}
}
/**
* @deprecated Use {@link GitUser} instead.
*/
public static class GHAuthor extends GitUser {
}
public static class Stats {
int total,additions,deletions;
@@ -110,8 +153,14 @@ public class GHCommit {
Stats stats;
List<Parent> parents;
User author,committer;
/**
public ShortInfo getCommitShortInfo() {
return commit;
}
/**
* The repository that contains the commit.
*/
public GHRepository getOwner() {

View File

@@ -31,11 +31,11 @@ package org.kohsuke.github;
public class GHCommitPointer {
private String ref, sha, label;
private GHUser user;
private GHRepository repository/*V2*/,repo/*V3*/;
private GHRepository repo;
/**
* This points to the user who owns
* the {@link #repository}.
* the {@link #getRepository()}.
*/
public GHUser getUser() {
return user;
@@ -45,7 +45,7 @@ public class GHCommitPointer {
* The repository that contains the commit.
*/
public GHRepository getRepository() {
return repo!=null ? repo : repository;
return repo;
}
/**
@@ -72,6 +72,5 @@ public class GHCommitPointer {
void wrapUp(GitHub root) {
if (user!=null) user.root = root;
if (repo!=null) repo.wrap(root);
if (repository!=null) repository.wrap(root);
}
}

View File

@@ -1,5 +1,7 @@
package org.kohsuke.github;
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
import java.net.URL;
import java.util.Date;
@@ -109,11 +111,13 @@ public class GHCompare {
return message;
}
public User getAuthor() {
@WithBridgeMethods(value=User.class,castRequired=true)
public GitUser getAuthor() {
return author;
}
public User getCommitter() {
@WithBridgeMethods(value=User.class,castRequired=true)
public GitUser getCommitter() {
return committer;
}
@@ -134,23 +138,13 @@ public class GHCompare {
}
}
public static class User {
private String name, email, date;
public String getName() {
return name;
}
public String getEmail() {
return email;
}
public Date getDate() {
return GitHub.parseDate(date);
}
/**
* @deprecated use {@link GitUser} instead.
*/
public static class User extends GitUser {
}
public static enum Status {
behind, ahead, identical;
behind, ahead, identical
}
}

View File

@@ -0,0 +1,171 @@
package org.kohsuke.github;
import java.io.IOException;
import javax.xml.bind.DatatypeConverter;
/**
* A Content of a repository.
*
* @author Alexandre COLLIGNON
*/
public class GHContent {
private GHRepository owner;
private String type;
private String encoding;
private long size;
private String sha;
private String name;
private String path;
private String content;
private String url; // this is the API url
private String git_url; // this is the Blob url
private String html_url; // this is the UI
public GHRepository getOwner() {
return owner;
}
public String getType() {
return type;
}
public String getEncoding() {
return encoding;
}
public long getSize() {
return size;
}
public String getSha() {
return sha;
}
public String getName() {
return name;
}
public String getPath() {
return path;
}
/**
* Retrieve the decoded content that is stored at this location.
*
* Due to the nature of GitHub's API, you're not guaranteed that
* the content will already be populated, so this may trigger
* network activity, and can throw an IOException.
**/
public String getContent() throws IOException {
return new String(DatatypeConverter.parseBase64Binary(getEncodedContent()));
}
/**
* Retrieve the raw content that is stored at this location.
*
* Due to the nature of GitHub's API, you're not guaranteed that
* the content will already be populated, so this may trigger
* network activity, and can throw an IOException.
**/
public String getEncodedContent() throws IOException {
if (content != null)
return content;
GHContent retrievedContent = owner.getFileContent(path);
this.size = retrievedContent.size;
this.sha = retrievedContent.sha;
this.content = retrievedContent.content;
this.url = retrievedContent.url;
this.git_url = retrievedContent.git_url;
this.html_url = retrievedContent.html_url;
return content;
}
public String getUrl() {
return url;
}
public String getGitUrl() {
return git_url;
}
public String getHtmlUrl() {
return html_url;
}
public boolean isFile() {
return "file".equals(type);
}
public boolean isDirectory() {
return "dir".equals(type);
}
public GHContentUpdateResponse update(String newContent, String commitMessage) throws IOException {
return update(newContent, commitMessage, null);
}
public GHContentUpdateResponse update(String newContent, String commitMessage, String branch) throws IOException {
String encodedContent = DatatypeConverter.printBase64Binary(newContent.getBytes());
Requester requester = new Requester(owner.root)
.with("path", path)
.with("message", commitMessage)
.with("sha", sha)
.with("content", encodedContent)
.method("PUT");
if (branch != null) {
requester.with("branch", branch);
}
GHContentUpdateResponse response = requester.to(getApiRoute(), GHContentUpdateResponse.class);
response.getContent().wrap(owner);
response.getCommit().wrapUp(owner);
this.content = encodedContent;
return response;
}
public GHContentUpdateResponse delete(String message) throws IOException {
return delete(message, null);
}
public GHContentUpdateResponse delete(String commitMessage, String branch) throws IOException {
Requester requester = new Requester(owner.root)
.with("path", path)
.with("message", commitMessage)
.with("sha", sha)
.method("DELETE");
if (branch != null) {
requester.with("branch", branch);
}
GHContentUpdateResponse response = requester.to(getApiRoute(), GHContentUpdateResponse.class);
response.getCommit().wrapUp(owner);
return response;
}
private String getApiRoute() {
return "/repos/" + owner.getOwnerName() + "/" + owner.getName() + "/contents/" + path;
}
GHContent wrap(GHRepository owner) {
this.owner = owner;
return this;
}
public static GHContent[] wrap(GHContent[] contents, GHRepository repository) {
for (GHContent unwrappedContent : contents) {
unwrappedContent.wrap(repository);
}
return contents;
}
}

View File

@@ -0,0 +1,18 @@
package org.kohsuke.github;
/**
* The response that is returned when updating
* repository content.
**/
public final class GHContentUpdateResponse {
private GHContent content;
private GHCommit commit;
public GHContent getContent() {
return content;
}
public GHCommit getCommit() {
return commit;
}
}

View File

@@ -6,6 +6,7 @@ package org.kohsuke.github;
* See http://developer.github.com/v3/events/types/
*
* @author Kohsuke Kawaguchi
* @see GHEventInfo
*/
public enum GHEvent {
COMMIT_COMMENT,
@@ -22,6 +23,7 @@ public enum GHEvent {
MEMBER,
PUBLIC,
PULL_REQUEST,
PULL_REQUEST_REVIEW_COMMENT,
PUSH,
TEAM_ADD,
WATCH

View File

@@ -1,10 +1,10 @@
package org.kohsuke.github;
import org.codehaus.jackson.node.ObjectNode;
import java.io.IOException;
import java.util.Date;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* Represents an event.
*
@@ -63,6 +63,13 @@ public class GHEventInfo {
return root.getUser(actor.getLogin());
}
/**
* Quick way to just get the actor of the login.
*/
public String getActorLogin() throws IOException {
return actor.getLogin();
}
public GHOrganization getOrganization() throws IOException {
return (org==null || org.getLogin()==null) ? null : root.getOrganization(org.getLogin());
}

View File

@@ -1,6 +1,7 @@
package org.kohsuke.github;
import java.io.Reader;
import java.util.List;
/**
* Base type for types used in databinding of the event payload.
@@ -8,6 +9,7 @@ import java.io.Reader;
* @see GitHub#parseEventPayload(Reader, Class)
* @see GHEventInfo#getPayload(Class)
*/
@SuppressWarnings("UnusedDeclaration")
public abstract class GHEventPayload {
protected GitHub root;
@@ -21,7 +23,7 @@ public abstract class GHEventPayload {
/**
* A pull request status has changed.
*
* @see http://developer.github.com/v3/activity/events/types/#pullrequestevent
* @see <a href="http://developer.github.com/v3/activity/events/types/#pullrequestevent">authoritative source</a>
*/
public static class PullRequest extends GHEventPayload {
private String action;
@@ -61,7 +63,7 @@ public abstract class GHEventPayload {
/**
* A comment was added to an issue
*
* @see http://developer.github.com/v3/activity/events/types/#issuecommentevent
* @see <a href="http://developer.github.com/v3/activity/events/types/#issuecommentevent">authoritative source</a>
*/
public static class IssueComment extends GHEventPayload {
private String action;
@@ -105,4 +107,88 @@ public abstract class GHEventPayload {
comment.wrapUp(issue);
}
}
/**
* A commit was pushed.
*
* @see <a href="http://developer.github.com/v3/activity/events/types/#pushevent">authoritative source</a>
*/
public static class Push extends GHEventPayload {
private String head, before;
private String ref;
private int size;
private List<PushCommit> commits;
/**
* The SHA of the HEAD commit on the repository
*/
public String getHead() {
return head;
}
/**
* This is undocumented, but it looks like this captures the commit that the ref was pointing to
* before the push.
*/
public String getBefore() {
return before;
}
/**
* The full Git ref that was pushed. Example: “refs/heads/master”
*/
public String getRef() {
return ref;
}
/**
* The number of commits in the push.
* Is this always the same as {@code getCommits().size()}?
*/
public int getSize() {
return size;
}
/**
* The list of pushed commits.
*/
public List<PushCommit> getCommits() {
return commits;
}
/**
* Commit in a push
*/
public static class PushCommit {
private GitUser author;
private String url, sha, message;
private boolean distinct;
public GitUser getAuthor() {
return author;
}
/**
* Points to the commit API resource.
*/
public String getUrl() {
return url;
}
public String getSha() {
return sha;
}
public String getMessage() {
return message;
}
/**
* Whether this commit is distinct from any that have been pushed before.
*/
public boolean isDistinct() {
return distinct;
}
}
}
}

View File

@@ -34,7 +34,7 @@ public final class GHHook {
public EnumSet<GHEvent> getEvents() {
EnumSet<GHEvent> s = EnumSet.noneOf(GHEvent.class);
for (String e : events)
Enum.valueOf(GHEvent.class,e.toUpperCase(Locale.ENGLISH));
s.add(Enum.valueOf(GHEvent.class,e.toUpperCase(Locale.ENGLISH)));
return s;
}

View File

@@ -49,7 +49,7 @@ public class GHIssue {
protected String closed_at;
protected int comments;
protected String body;
protected List<String> labels;
protected List<Label> labels;
protected GHUser user;
protected String title, created_at, html_url;
protected GHIssue.PullRequest pull_request;
@@ -58,6 +58,24 @@ public class GHIssue {
protected int id;
protected GHUser closed_by;
public static class Label {
private String url;
private String name;
private String color;
public String getUrl() {
return url;
}
public String getName() {
return name;
}
public String getColor() {
return color;
}
}
/*package*/ GHIssue wrap(GHRepository owner) {
this.owner = owner;
this.root = owner.root;
@@ -111,7 +129,7 @@ public class GHIssue {
return Enum.valueOf(GHIssueState.class, state.toUpperCase(Locale.ENGLISH));
}
public Collection<String> getLabels() {
public Collection<Label> getLabels() {
if(labels == null){
return Collections.EMPTY_LIST;
}
@@ -172,7 +190,7 @@ public class GHIssue {
}
public void setLabels(String... labels) throws IOException {
edit("assignee",labels);
edit("labels",labels);
}
/**

View File

@@ -10,9 +10,9 @@ import org.apache.commons.lang.builder.ToStringBuilder;
public class GHKey {
/*package almost final*/ GitHub root;
private String url, key, title;
private boolean verified;
private int id;
protected String url, key, title;
protected boolean verified;
protected int id;
public int getId() {
return id;

View File

@@ -1,5 +1,6 @@
package org.kohsuke.github;
import java.io.IOException;
import java.util.Date;
import java.util.Locale;
@@ -65,6 +66,21 @@ public class GHMilestone {
return Enum.valueOf(GHMilestoneState.class, state.toUpperCase(Locale.ENGLISH));
}
/**
* Closes this issue.
*/
public void close() throws IOException {
edit("state", "closed");
}
private void edit(String key, Object value) throws IOException {
new Requester(root)._with(key, value).method("PATCH").to(getApiRoute());
}
protected String getApiRoute() {
return "/repos/"+owner.getOwnerName()+"/"+owner.getName()+"/milestones/"+number;
}
public GHMilestone wrap(GHRepository repo) {
this.owner = repo;
this.root = repo.root;

View File

@@ -3,7 +3,12 @@ package org.kohsuke.github;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
/**
* Represents the account that's logging into GitHub.
@@ -29,13 +34,74 @@ public class GHMyself extends GHUser {
/**
* Returns the read-only list of all the pulic keys of the current user.
*
* NOTE: When using OAuth authenticaiton, the READ/WRITE User scope is
* required by the GitHub APIs, otherwise you will get a 404 NOT FOUND.
*
* @return
* Always non-null.
*/
public List<GHKey> getPublicKeys() throws IOException {
return Collections.unmodifiableList(Arrays.asList(root.retrieve().to("/user/keys", GHKey[].class)));
}
/**
* Returns the read-only list of all the public verified keys of the current user.
*
* Differently from the getPublicKeys() method, the retrieval of the user's
* verified public keys does not require any READ/WRITE OAuth Scope to the
* user's profile.
*
* @return
* Always non-null.
*/
public List<GHVerifiedKey> getPublicVerifiedKeys() throws IOException {
return Collections.unmodifiableList(Arrays.asList(root.retrieve().to(
"/users/" + getLogin() + "/keys", GHVerifiedKey[].class)));
}
/**
* Gets the organization that this user belongs to.
*/
public GHPersonSet<GHOrganization> getAllOrganizations() throws IOException {
GHPersonSet<GHOrganization> orgs = new GHPersonSet<GHOrganization>();
Set<String> names = new HashSet<String>();
for (GHOrganization o : root.retrieve().to("/user/orgs", GHOrganization[].class)) {
if (names.add(o.getLogin())) // in case of rumoured duplicates in the data
orgs.add(root.getOrganization(o.getLogin()));
}
return orgs;
}
/**
* Gets the all repositories this user owns (public and private).
*/
public synchronized Map<String,GHRepository> getAllRepositories() throws IOException {
Map<String,GHRepository> repositories = new TreeMap<String, GHRepository>();
for (GHRepository r : listAllRepositories()) {
repositories.put(r.getName(),r);
}
return Collections.unmodifiableMap(repositories);
}
/**
* Lists up all repositories this user owns (public and private).
*
* Unlike {@link #getAllRepositories()}, this does not wait until all the repositories are returned.
*/
public PagedIterable<GHRepository> listAllRepositories() {
return new PagedIterable<GHRepository>() {
public PagedIterator<GHRepository> iterator() {
return new PagedIterator<GHRepository>(root.retrieve().asIterator("/user/repos", GHRepository[].class)) {
@Override
protected void wrapUp(GHRepository[] page) {
for (GHRepository c : page)
c.wrap(root);
}
};
}
};
}
// public void addEmails(Collection<String> emails) throws IOException {
//// new Requester(root,ApiVersion.V3).withCredential().to("/user/emails");
// root.retrieveWithAuth3()

View File

@@ -1,7 +1,6 @@
package org.kohsuke.github;
import java.io.IOException;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -78,26 +77,44 @@ public class GHOrganization extends GHPerson {
}
/**
* All the members of this organization.
* @deprecated use {@link #listMembers()}
*/
public List<GHUser> getMembers() throws IOException {
return new AbstractList<GHUser>() {
// these are shallow objects with only some limited values filled out
// TODO: it's better to allow objects to fill themselves in later when missing values are requested
final GHUser[] shallow = root.retrieve().to("/orgs/" + login + "/members", GHUser[].class);
return listMembers().asList();
}
@Override
public GHUser get(int index) {
try {
return root.getUser(shallow[index].getLogin());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* All the members of this organization.
*/
public PagedIterable<GHUser> listMembers() throws IOException {
return listMembers("members");
}
@Override
public int size() {
return shallow.length;
/**
* All the public members of this organization.
*/
public PagedIterable<GHUser> listPublicMembers() throws IOException {
return listMembers("public_members");
}
private PagedIterable<GHUser> listMembers(String suffix) throws IOException {
return listMembers(suffix, null);
}
public PagedIterable<GHUser> listMembersWithFilter(String filter) throws IOException {
return listMembers("members", filter);
}
private PagedIterable<GHUser> listMembers(final String suffix, final String filter) throws IOException {
return new PagedIterable<GHUser>() {
public PagedIterator<GHUser> iterator() {
String filterParams = (filter == null) ? "" : ("?filter=" + filter);
return new PagedIterator<GHUser>(root.retrieve().asIterator(String.format("/orgs/%s/%s%s", login, suffix, filterParams), GHUser[].class)) {
@Override
protected void wrapUp(GHUser[] users) {
GHUser.wrap(users, root);
}
};
}
};
}
@@ -130,10 +147,13 @@ public class GHOrganization extends GHPerson {
/**
* List up repositories that has some open pull requests.
*
* This used to be an efficient method that didn't involve traversing every repository, but now
* it doesn't do any optimization.
*/
public List<GHRepository> getRepositoriesWithOpenPullRequests() throws IOException {
List<GHRepository> r = new ArrayList<GHRepository>();
for (GHRepository repository : root.retrieve().to("/orgs/" + login + "/repos", GHRepository[].class)) {
for (GHRepository repository : listRepositories()) {
repository.wrap(root);
List<GHPullRequest> pullRequests = repository.getPullRequests(GHIssueState.OPEN);
if (pullRequests.size() > 0) {
@@ -153,4 +173,43 @@ public class GHOrganization extends GHPerson {
}
return all;
}
/**
* Lists events performed by a user (this includes private events if the caller is authenticated.
*/
public PagedIterable<GHEventInfo> listEvents() throws IOException {
return new PagedIterable<GHEventInfo>() {
public PagedIterator<GHEventInfo> iterator() {
return new PagedIterator<GHEventInfo>(root.retrieve().asIterator(String.format("/orgs/%s/events", login), GHEventInfo[].class)) {
@Override
protected void wrapUp(GHEventInfo[] page) {
for (GHEventInfo c : page)
c.wrapUp(root);
}
};
}
};
}
/**
* Lists up all the repositories using the specified page size.
*
* @param pageSize size for each page of items returned by GitHub. Maximum page size is 100.
*
* Unlike {@link #getRepositories()}, this does not wait until all the repositories are returned.
*/
@Override
public PagedIterable<GHRepository> listRepositories(final int pageSize) {
return new PagedIterable<GHRepository>() {
public PagedIterator<GHRepository> iterator() {
return new PagedIterator<GHRepository>(root.retrieve().asIterator("/orgs/" + login + "/repos?per_page=" + pageSize, GHRepository[].class)) {
@Override
protected void wrapUp(GHRepository[] page) {
for (GHRepository c : page)
c.wrap(root);
}
};
}
};
}
}

View File

@@ -54,6 +54,36 @@ public abstract class GHPerson {
return Collections.unmodifiableMap(repositories);
}
/**
* Lists up all the repositories using a 30 items page size.
*
* Unlike {@link #getRepositories()}, this does not wait until all the repositories are returned.
*/
public PagedIterable<GHRepository> listRepositories() {
return listRepositories(30);
}
/**
* Lists up all the repositories using the specified page size.
*
* @param pageSize size for each page of items returned by GitHub. Maximum page size is 100.
*
* Unlike {@link #getRepositories()}, this does not wait until all the repositories are returned.
*/
public PagedIterable<GHRepository> listRepositories(final int pageSize) {
return new PagedIterable<GHRepository>() {
public PagedIterator<GHRepository> iterator() {
return new PagedIterator<GHRepository>(root.retrieve().asIterator("/users/" + login + "/repos?per_page=" + pageSize, GHRepository[].class)) {
@Override
protected void wrapUp(GHRepository[] page) {
for (GHRepository c : page)
c.wrap(root);
}
};
}
};
}
/**
* Loads repository list in a pagenated fashion.
*
@@ -63,6 +93,9 @@ public abstract class GHPerson {
*
* Every {@link Iterator#next()} call results in I/O. Exceptions that occur during the processing is wrapped
* into {@link Error}.
*
* @deprecated
* Use {@link #listRepositories()}
*/
public synchronized Iterable<List<GHRepository>> iterateRepositories(final int pageSize) {
return new Iterable<List<GHRepository>>() {
@@ -102,6 +135,11 @@ public abstract class GHPerson {
}
}
/**
* Lists events for an organization or an user.
*/
public abstract PagedIterable<GHEventInfo> listEvents() throws IOException;
/**
* Gravatar ID of this user, like 0cb9832a01c22c083390f3c5dcb64105
*
@@ -202,5 +240,4 @@ public abstract class GHPerson {
populate();
return followers;
}
}

View File

@@ -27,6 +27,7 @@ import java.io.IOException;
import java.net.URL;
import java.util.Collection;
import java.util.Date;
import java.util.Locale;
/**
* A pull request.
@@ -118,7 +119,7 @@ public class GHPullRequest extends GHIssue {
}
@Override
public Collection<String> getLabels() {
public Collection<Label> getLabels() {
return super.getLabels();
}
@@ -186,4 +187,34 @@ public class GHPullRequest extends GHIssue {
root.retrieve().to(url, this);
}
/**
* Retrieves all the commits associated to this pull request.
*/
public PagedIterable<GHPullRequestCommitDetail> listCommits() {
return new PagedIterable<GHPullRequestCommitDetail>() {
public PagedIterator<GHPullRequestCommitDetail> iterator() {
return new PagedIterator<GHPullRequestCommitDetail>(root.retrieve().asIterator(
String.format("%s/commits", getApiURL().getPath()),
GHPullRequestCommitDetail[].class)) {
@Override
protected void wrapUp(GHPullRequestCommitDetail[] page) {
}
};
}
};
}
/**
* Merge this pull request.
*
* The equivalent of the big green "Merge pull request" button.
*
* @param msg
* Commit message. If null, the default one will be used.
*/
public void merge(String msg) throws IOException {
new Requester(root).method("PUT").with("commit_message",msg).to(getApiRoute()+"/merge");
}
}

View File

@@ -0,0 +1,129 @@
/*
* The MIT License
*
* Copyright (c) 2013, Luca Milanesio
*
* 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 com.infradna.tool.bridge_method_injector.WithBridgeMethods;
import java.net.URL;
/**
* Commit detail inside a {@link GHPullRequest}.
*
* @author Luca Milanesio
*/
public class GHPullRequestCommitDetail {
/**
* @deprecated Use {@link GitUser}
*/
public static class Authorship extends GitUser {}
public static class Tree {
String sha;
String url;
public String getSha() {
return sha;
}
public URL getUrl() {
return GitHub.parseURL(url);
}
}
public static class Commit {
Authorship author;
Authorship committer;
String message;
Tree tree;
String url;
int comment_count;
@WithBridgeMethods(value=Authorship.class,castRequired=true)
public GitUser getAuthor() {
return author;
}
@WithBridgeMethods(value=Authorship.class,castRequired=true)
public GitUser getCommitter() {
return committer;
}
public String getMessage() {
return message;
}
public URL getUrl() {
return GitHub.parseURL(url);
}
public int getComment_count() {
return comment_count;
}
}
public static class CommitPointer {
String sha;
String url;
String html_url;
public URL getUrl() {
return GitHub.parseURL(url);
}
public URL getHtml_url() {
return GitHub.parseURL(html_url);
}
public String getSha() {
return sha;
}
}
String sha;
Commit commit;
String url;
String html_url;
String comments_url;
CommitPointer[] parents;
public String getSha() {
return sha;
}
public Commit getCommit() {
return commit;
}
public URL getApiUrl() {
return GitHub.parseURL(url);
}
public URL getUrl() {
return GitHub.parseURL(html_url);
}
public URL getCommentsUrl() {
return GitHub.parseURL(comments_url);
}
public CommitPointer[] getParents() {
return parents;
}
}

View File

@@ -0,0 +1,195 @@
package org.kohsuke.github;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import static java.lang.String.format;
/**
* Release in a github repository.
*
* @see GHRepository#getReleases()
* @see GHRepository#createRelease(String)
*/
public class GHRelease {
GitHub root;
GHRepository owner;
private String url;
private String html_url;
private String assets_url;
private String upload_url;
private long id;
private String tag_name;
private String target_commitish;
private String name;
private String body;
private boolean draft;
private boolean prerelease;
private Date created_at;
private Date published_at;
public String getAssetsUrl() {
return assets_url;
}
public void setAssetsUrl(String assets_url) {
this.assets_url = assets_url;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public Date getCreatedAt() {
return created_at;
}
public void setCreatedAt(Date created_at) {
this.created_at = created_at;
}
public boolean isDraft() {
return draft;
}
public void setDraft(boolean draft) {
this.draft = draft;
}
public String getHtmlUrl() {
return html_url;
}
public void setHtmlUrl(String html_url) {
this.html_url = html_url;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public GHRepository getOwner() {
return owner;
}
public void setOwner(GHRepository owner) {
this.owner = owner;
}
public boolean isPrerelease() {
return prerelease;
}
public void setPrerelease(boolean prerelease) {
this.prerelease = prerelease;
}
public Date getPublished_at() {
return published_at;
}
public void setPublished_at(Date published_at) {
this.published_at = published_at;
}
public GitHub getRoot() {
return root;
}
public void setRoot(GitHub root) {
this.root = root;
}
public String getTagName() {
return tag_name;
}
public void setTagName(String tag_name) {
this.tag_name = tag_name;
}
public String getTargetCommitish() {
return target_commitish;
}
public void setTargetCommitish(String target_commitish) {
this.target_commitish = target_commitish;
}
public String getUploadUrl() {
return upload_url;
}
public void setUploadUrl(String upload_url) {
this.upload_url = upload_url;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
GHRelease wrap(GHRepository owner) {
this.owner = owner;
this.root = owner.root;
return this;
}
static GHRelease[] wrap(GHRelease[] releases, GHRepository owner) {
for (GHRelease release : releases) {
release.wrap(owner);
}
return releases;
}
/**
* Because github relies on SNI (http://en.wikipedia.org/wiki/Server_Name_Indication) this method will only work on
* Java 7 or greater. Options for fixing this for earlier JVMs can be found here
* http://stackoverflow.com/questions/12361090/server-name-indication-sni-on-java but involve more complicated
* handling of the HTTP requests to github's API.
*
* @throws IOException
*/
public GHAsset uploadAsset(File file, String contentType) throws IOException {
Requester builder = new Requester(owner.root);
String url = format("https://uploads.github.com%sreleases/%d/assets?name=%s",
owner.getApiTailUrl(""), getId(), file.getName());
return builder.contentType(contentType)
.with(new FileInputStream(file))
.to(url, GHAsset.class).wrap(this);
}
public List<GHAsset> getAssets() throws IOException {
Requester builder = new Requester(owner.root);
GHAsset[] assets = builder
.method("GET")
.to(owner.getApiTailUrl(format("releases/%d/assets", id)), GHAsset[].class);
return Arrays.asList(GHAsset.wrap(assets, this));
}
}

View File

@@ -0,0 +1,80 @@
package org.kohsuke.github;
import java.io.IOException;
/**
* Builder pattern for creating a {@link GHRelease}
*
* @see GHRepository#createRelease(String)
*/
public class GHReleaseBuilder {
private final GHRepository repo;
private final Requester builder;
public GHReleaseBuilder(GHRepository ghRepository, String tag) {
this.repo = ghRepository;
this.builder = new Requester(repo.root);
builder.with("tag_name", tag);
}
/**
* @param body The release notes body.
*/
public GHReleaseBuilder body(String body) {
if (body != null) {
builder.with("body", body);
}
return this;
}
/**
* Specifies the commitish value that determines where the Git tag is created from. Can be any branch or
* commit SHA.
*
* @param commitish Defaults to the repositorys default branch (usually "master"). Unused if the Git tag
* already exists.
* @return
*/
public GHReleaseBuilder commitish(String commitish) {
if (commitish != null) {
builder.with("target_commitish", commitish);
}
return this;
}
/**
* Optional.
*
* @param draft {@code true} to create a draft (unpublished) release, {@code false} to create a published one.
* Default is {@code false}.
*/
public GHReleaseBuilder draft(boolean draft) {
builder.with("draft", draft);
return this;
}
/**
* @param name the name of the release
*/
public GHReleaseBuilder name(String name) {
if (name != null) {
builder.with("name", name);
}
return this;
}
/**
* Optional
*
* @param prerelease {@code true} to identify the release as a prerelease. {@code false} to identify the release
* as a full release. Default is {@code false}.
*/
public GHReleaseBuilder prerelease(boolean prerelease) {
builder.with("prerelease", prerelease);
return this;
}
public GHRelease create() throws IOException {
return builder.to(repo.getApiTailUrl("releases"), GHRelease.class).wrap(repo);
}
}

View File

@@ -23,8 +23,10 @@
*/
package org.kohsuke.github;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
import javax.xml.bind.DatatypeConverter;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.URL;
@@ -58,7 +60,9 @@ public class GHRepository {
private String url; // this is the API url
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 boolean has_issues, has_wiki, fork, has_downloads;
@JsonProperty("private")
private boolean _private;
private int watchers,forks,open_issues,size;
private String created_at, pushed_at;
private Map<Integer,GHMilestone> milestones = new HashMap<Integer, GHMilestone>();
@@ -143,7 +147,40 @@ public class GHRepository {
}
public List<GHIssue> getIssues(GHIssueState state) throws IOException {
return Arrays.asList(GHIssue.wrap(root.retrieve().to("/repos/" + owner.login + "/" + name + "/issues?state=" + state.toString().toLowerCase(), GHIssue[].class), this));
return listIssues(state).asList();
}
public List<GHIssue> getIssues(GHIssueState state, GHMilestone milestone) throws IOException {
return Arrays.asList(GHIssue.wrap(root.retrieve()
.to(String.format("/repos/%s/%s/issues?state=%s&milestone=%s", owner.login, name,
state.toString().toLowerCase(), milestone == null ? "none" : "" + milestone.getNumber()),
GHIssue[].class), this));
}
/**
* Lists up all the issues in this repository.
*/
public PagedIterable<GHIssue> listIssues(final GHIssueState state) {
return new PagedIterable<GHIssue>() {
public PagedIterator<GHIssue> iterator() {
return new PagedIterator<GHIssue>(root.retrieve().asIterator(getApiTailUrl("issues?state="+state.toString().toLowerCase(Locale.ENGLISH)), GHIssue[].class)) {
@Override
protected void wrapUp(GHIssue[] page) {
for (GHIssue c : page)
c.wrap(GHRepository.this);
}
};
}
};
}
public GHReleaseBuilder createRelease(String tag) {
return new GHReleaseBuilder(this,tag);
}
public List<GHRelease> getReleases() throws IOException {
return Arrays.asList(GHRelease.wrap(root.retrieve().to("/repos/" + owner.login + "/" + name + "/releases",
GHRelease[].class), this));
}
protected String getOwnerName() {
@@ -519,6 +556,22 @@ public class GHRepository {
.to(String.format("/repos/%s/%s/statuses/%s",owner.login,this.name,sha1),GHCommitStatus.class).wrapUp(root);
}
/**
* Lists repository events.
*/
public PagedIterable<GHEventInfo> listEvents() throws IOException {
return new PagedIterable<GHEventInfo>() {
public PagedIterator<GHEventInfo> iterator() {
return new PagedIterator<GHEventInfo>(root.retrieve().asIterator(String.format("/repos/%s/%s/events", owner.login, name), GHEventInfo[].class)) {
@Override
protected void wrapUp(GHEventInfo[] page) {
for (GHEventInfo c : page)
c.wrapUp(root);
}
};
}
};
}
/**
*
@@ -691,7 +744,66 @@ public class GHRepository {
}
return m;
}
public GHContent getFileContent(String path) throws IOException {
return getFileContent(path, null);
}
public GHContent getFileContent(String path, String ref) throws IOException {
Requester requester = root.retrieve();
String target = String.format("/repos/%s/%s/contents/%s", owner.login, name, path);
if (ref != null)
target = target + "?ref=" + ref;
return requester.to(target, GHContent.class).wrap(this);
}
public List<GHContent> getDirectoryContent(String path) throws IOException {
return getDirectoryContent(path, null);
}
public List<GHContent> getDirectoryContent(String path, String ref) throws IOException {
Requester requester = root.retrieve();
String target = String.format("/repos/%s/%s/contents/%s", owner.login, name, path);
if (ref != null)
target = target + "?ref=" + ref;
GHContent[] files = requester.to(target, GHContent[].class);
GHContent.wrap(files, this);
return Arrays.asList(files);
}
public GHContent getReadme() throws Exception {
return getFileContent("readme");
}
public GHContentUpdateResponse createContent(String content, String commitMessage, String path) throws IOException {
return createContent(content, commitMessage, path, null);
}
public GHContentUpdateResponse createContent(String content, String commitMessage, String path, String branch) throws IOException {
Requester requester = new Requester(root)
.with("path", path)
.with("message", commitMessage)
.with("content", DatatypeConverter.printBase64Binary(content.getBytes()))
.method("PUT");
if (branch != null) {
requester.with("branch", branch);
}
GHContentUpdateResponse response = requester.to(getApiTailUrl("contents/" + path), GHContentUpdateResponse.class);
response.getContent().wrap(this);
response.getCommit().wrapUp(this);
return response;
}
public GHMilestone createMilestone(String title, String description) throws IOException {
return new Requester(root)
.with("title", title).with("description", description).method("POST").to(getApiTailUrl("milestones"), GHMilestone.class).wrap(this);

View File

@@ -49,6 +49,18 @@ public class GHTeam {
return new HashSet<GHUser>(Arrays.asList(GHUser.wrap(org.root.retrieve().to(api("/members"), GHUser[].class), org.root)));
}
/**
* Checks if this team has the specified user as a member.
*/
public boolean hasMember(GHUser user) {
try {
org.root.retrieve().to("/teams/" + id + "/members/" + user.getLogin());
return true;
} catch (IOException ignore) {
return false;
}
}
public Map<String,GHRepository> getRepositories() throws IOException {
GHRepository[] repos = org.root.retrieve().to(api("/repos"), GHRepository[].class);
Map<String,GHRepository> m = new TreeMap<String, GHRepository>();

View File

@@ -76,6 +76,13 @@ public class GHUser extends GHPerson {
return org.hasMember(this);
}
/**
* Returns true if this user belongs to the specified team.
*/
public boolean isMemberOf(GHTeam team) {
return team.hasMember(this);
}
/**
* Returns true if this user belongs to the specified organization as a public member.
*/
@@ -103,6 +110,23 @@ public class GHUser extends GHPerson {
return orgs;
}
/**
* Lists events performed by a user (this includes private events if the caller is authenticated.
*/
public PagedIterable<GHEventInfo> listEvents() throws IOException {
return new PagedIterable<GHEventInfo>() {
public PagedIterator<GHEventInfo> iterator() {
return new PagedIterator<GHEventInfo>(root.retrieve().asIterator(String.format("/users/%s/events", login), GHEventInfo[].class)) {
@Override
protected void wrapUp(GHEventInfo[] page) {
for (GHEventInfo c : page)
c.wrapUp(root);
}
};
}
};
}
@Override
public String toString() {
return "User:"+login;

View File

@@ -0,0 +1,13 @@
package org.kohsuke.github;
public class GHVerifiedKey extends GHKey {
public GHVerifiedKey() {
this.verified = true;
}
@Override
public String getTitle() {
return (title == null ? "key-" + id : title);
}
}

View File

@@ -23,12 +23,7 @@
*/
package org.kohsuke.github;
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
import org.apache.commons.codec.binary.Base64;
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 static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.*;
import java.io.File;
import java.io.FileInputStream;
@@ -47,7 +42,13 @@ import java.util.Map;
import java.util.Properties;
import java.util.TimeZone;
import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.*;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.introspect.VisibilityChecker.Std;
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
/**
* Root of the GitHub API.
@@ -123,7 +124,7 @@ public class GitHub {
}
}
if (login==null)
if (login==null && encodedAuthorization!=null)
login = getMyself().getLogin();
this.login = login;
}
@@ -192,8 +193,16 @@ public class GitHub {
return new GitHub(null,null,null);
}
/**
* Is this an anonymous connection
* @return {@code true} if operations that require authentication will fail.
*/
public boolean isAnonymous() {
return login==null && encodedAuthorization==null;
}
/*package*/ void requireCredential() {
if (login==null && encodedAuthorization==null)
if (isAnonymous())
throw new IllegalStateException("This operation requires a credential but none is given to the GitHub constructor");
}
@@ -389,7 +398,7 @@ public class GitHub {
static {
MAPPER.setVisibilityChecker(new Std(NONE, NONE, NONE, NONE, ANY));
MAPPER.getDeserializationConfig().set(Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
}
private static final String GITHUB_URL = "https://api.github.com";

View File

@@ -0,0 +1,38 @@
package org.kohsuke.github;
import java.util.Date;
/**
* Represents a user in Git who authors/commits a commit.
*
* In contrast, {@link GHUser} is an user of GitHub. Because Git allows a person to
* use multiple e-mail addresses and names when creating a commit, there's generally
* no meaningful mapping between {@link GHUser} and {@link GitUser}.
*
* @author Kohsuke Kawaguchi
*/
public class GitUser {
private String name, email, date;
/**
* Human readable name of the user, such as "Kohsuke Kawaguchi"
*/
public String getName() {
return name;
}
/**
* E-mail address, such as "foo@example.com"
*/
public String getEmail() {
return email;
}
/**
* This field doesn't appear to be consistently available in all the situations where this class
* is used.
*/
public Date getDate() {
return GitHub.parseDate(date);
}
}

View File

@@ -25,6 +25,7 @@ package org.kohsuke.github;
import org.apache.commons.io.IOUtils;
import javax.net.ssl.HttpsURLConnection;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
@@ -47,7 +48,7 @@ import java.util.NoSuchElementException;
import java.util.Set;
import java.util.zip.GZIPInputStream;
import static org.kohsuke.github.GitHub.*;
import static org.kohsuke.github.GitHub.MAPPER;
/**
* A builder pattern for making HTTP call and parsing its output.
@@ -62,6 +63,8 @@ class Requester {
* Request method.
*/
private String method = "POST";
private String contentType = "application/x-www-form-urlencoded";
private InputStream body;
private static class Entry {
String key;
@@ -113,6 +116,11 @@ class Requester {
return _with(key, value);
}
public Requester with(InputStream body) {
this.body = body;
return this;
}
public Requester _with(String key, Object value) {
if (value!=null) {
args.add(new Entry(key,value));
@@ -125,6 +133,11 @@ class Requester {
return this;
}
public Requester contentType(String contentType) {
this.contentType = contentType;
return this;
}
public void to(String tailApiUrl) throws IOException {
to(tailApiUrl,null);
}
@@ -162,13 +175,25 @@ class Requester {
if (!method.equals("GET")) {
uc.setDoOutput(true);
uc.setRequestProperty("Content-type","application/x-www-form-urlencoded");
uc.setRequestProperty("Content-type", contentType);
Map json = new HashMap();
for (Entry e : args) {
json.put(e.key, e.value);
if (body == null) {
Map json = new HashMap();
for (Entry e : args) {
json.put(e.key, e.value);
}
MAPPER.writeValue(uc.getOutputStream(), json);
} else {
try {
byte[] bytes = new byte[32768];
int read = 0;
while ((read = body.read(bytes)) != -1) {
uc.getOutputStream().write(bytes, 0, read);
}
} finally {
body.close();
}
}
MAPPER.writeValue(uc.getOutputStream(),json);
}
try {
@@ -269,7 +294,7 @@ class Requester {
private HttpURLConnection setupConnection(URL url) throws IOException {
HttpURLConnection uc = (HttpURLConnection) url.openConnection();
HttpsURLConnection uc = (HttpsURLConnection) url.openConnection();
// if the authentication is needed but no credential is given, try it anyway (so that some calls
// that do work with anonymous access in the reduced form should still work.)

View File

@@ -7,7 +7,6 @@ import java.util.Arrays;
*/
public class Foo {
public static void main(String[] args) throws Exception {
System.out.println(GitHub.connect().createToken(
Arrays.asList("user", "repo", "delete_repo", "notifications", "gist"), "GitHub API", null).getToken());
System.out.println(GitHub.connect().getOrganization("cloudbees").getRepository("grandcentral").isPrivate());
}
}

View File

@@ -1,15 +1,30 @@
package org.kohsuke;
import junit.framework.TestCase;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import org.kohsuke.github.GHBranch;
import org.kohsuke.github.GHCommit;
import org.kohsuke.github.GHCommit.File;
import org.kohsuke.github.GHCommitComment;
import org.kohsuke.github.GHCommitState;
import org.kohsuke.github.GHCommitStatus;
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.GHIssue;
import org.kohsuke.github.GHIssueComment;
import org.kohsuke.github.GHIssueState;
@@ -25,40 +40,51 @@ 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.
*/
public class AppTest extends TestCase {
public class AppTest {
private GitHub gitHub;
@Override
@Before
public void setUp() throws Exception {
super.setUp();
gitHub = GitHub.connect();
}
private String getTestRepositoryName() throws IOException {
return getUser().getLogin() + "/github-api-test";
}
@Test
public void testRepoCRUD() throws Exception {
GHRepository r = gitHub.createRepository("github-api-test", "a test repository", "http://github-api.kohsuke.org/", true);
String targetName = "github-api-test-rename2";
deleteRepository("github-api-test-rename");
deleteRepository(targetName);
GHRepository r = gitHub.createRepository("github-api-test-rename", "a test repository", "http://github-api.kohsuke.org/", true);
r.enableIssueTracker(false);
r.enableDownloads(false);
r.enableWiki(false);
r.renameTo("github-api-test2");
gitHub.getMyself().getRepository("github-api-test2").delete();
r.renameTo(targetName);
getUser().getRepository(targetName).delete();
}
private void deleteRepository(final String name) throws IOException {
GHRepository repository = getUser().getRepository(name);
if(repository != null) {
repository.delete();
}
}
@Test
public void testCredentialValid() throws IOException {
assertTrue(gitHub.isCredentialValid());
assertFalse(GitHub.connect("totally", "bogus").isCredentialValid());
GitHub connect = GitHub.connect("totally", "bogus");
assertFalse(connect.isCredentialValid());
}
@Test
public void testIssueWithNoComment() throws IOException {
GHRepository repository = gitHub.getRepository("kohsuke/test");
List<GHIssueComment> v = repository.getIssue(4).getComments();
@@ -70,25 +96,103 @@ public class AppTest extends TestCase {
assertTrue(v.size() == 3);
}
@Test
public void testCreateIssue() throws IOException {
GHUser u = gitHub.getUser("kohsuke");
GHRepository r = u.getRepository("test");
GHMilestone someMilestone = r.listMilestones(GHIssueState.CLOSED).iterator().next();
GHIssue o = r.createIssue("testing").body("this is body").assignee(u).label("bug").label("question").milestone(someMilestone).create();
System.out.println(o.getUrl());
GHUser u = getUser();
GHRepository repository = getTestRepository();
GHMilestone milestone = repository.createMilestone(System.currentTimeMillis() + "", "Test Milestone");
GHIssue o = repository.createIssue("testing")
.body("this is body")
.assignee(u)
.label("bug")
.label("question")
.milestone(milestone)
.create();
assertNotNull(o);
o.close();
}
@Test
public void testGetIssues() throws Exception {
List<GHIssue> closedIssues = gitHub.getUser("kohsuke").getRepository("github-api").getIssues(GHIssueState.CLOSED);
// prior to using PagedIterable GHRepository.getIssues(GHIssueState) would only retrieve 30 issues
assertTrue(closedIssues.size() > 30);
}
private GHRepository getTestRepository() throws IOException {
GHRepository repository;
try {
repository = gitHub.getRepository(getTestRepositoryName());
} catch (IOException e) {
repository = gitHub.createRepository("github-api-test", "A test repository for testing" +
"the github-api project", "http://github-api.kohsuke.org/", true);
try {
Thread.sleep(2000);
} catch (InterruptedException e1) {
throw new RuntimeException(e.getMessage(), e);
}
repository.enableIssueTracker(true);
repository.enableDownloads(true);
repository.enableWiki(true);
}
return repository;
}
private GHUser getUser() {
try {
return gitHub.getMyself();
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
@Test
public void testListIssues() throws IOException {
GHUser u = getUser();
GHRepository repository = getTestRepository();
GHMilestone milestone = repository.createMilestone(System.currentTimeMillis() + "", "Test Milestone");
milestone.close();
GHIssue unhomed = null;
GHIssue homed = null;
try {
unhomed = repository.createIssue("testing").body("this is body")
.assignee(u)
.label("bug")
.label("question")
.create();
assertEquals(unhomed.getNumber(), repository.getIssues(GHIssueState.OPEN, null).get(0).getNumber());
homed = repository.createIssue("testing").body("this is body")
.assignee(u)
.label("bug")
.label("question")
.milestone(milestone)
.create();
assertEquals(homed.getNumber(), repository.getIssues(GHIssueState.OPEN, milestone).get(0).getNumber());
} finally {
if (unhomed != null) {
unhomed.close();
}
if (homed != null) {
homed.close();
}
}
}
@Test
public void testRateLimit() throws IOException {
System.out.println(gitHub.getRateLimit());
}
@Test
public void testMyOrganizations() throws IOException {
Map<String, GHOrganization> org = gitHub.getMyOrganizations();
assertFalse(org.keySet().contains(null));
System.out.println(org);
}
@Test
public void testFetchPullRequest() throws Exception {
GHRepository r = gitHub.getOrganization("jenkinsci").getRepository("jenkins");
assertEquals("master",r.getMasterBranch());
@@ -96,8 +200,9 @@ public class AppTest extends TestCase {
r.getPullRequests(GHIssueState.OPEN);
}
@Test
public void testFetchPullRequestAsList() throws Exception {
GHRepository r = gitHub.getOrganization("symfony").getRepository("symfony-docs");
GHRepository r = gitHub.getRepository("kohsuke/github-api");
assertEquals("master", r.getMasterBranch());
PagedIterable<GHPullRequest> i = r.listPullRequests(GHIssueState.CLOSED);
List<GHPullRequest> prs = i.asList();
@@ -105,50 +210,56 @@ public class AppTest extends TestCase {
assertTrue(prs.size() > 0);
}
@Test
public void testRepoPermissions() throws Exception {
kohsuke();
GHRepository r = gitHub.getOrganization("jenkinsci").getRepository("jenkins");
assertTrue(r.hasPullAccess());
r = gitHub.getOrganization("github").getRepository("tire");
r = gitHub.getOrganization("github").getRepository("hub");
assertFalse(r.hasAdminAccess());
}
@Test
public void testGetMyself() throws Exception {
GHMyself me = gitHub.getMyself();
System.out.println(me);
GHUser u = gitHub.getUser("kohsuke2");
System.out.println(u);
for (List<GHRepository> lst : me.iterateRepositories(100)) {
for (GHRepository r : lst) {
System.out.println(r.getPushedAt());
}
}
assertNotNull(me);
assertNotNull(gitHub.getUser("kohsuke2"));
PagedIterable<GHRepository> ghRepositories = me.listRepositories();
assertTrue(ghRepositories.iterator().hasNext());
}
@Test
public void testPublicKeys() throws Exception {
List<GHKey> keys = gitHub.getMyself().getPublicKeys();
System.out.println(keys);
assertFalse(keys.isEmpty());
}
public void tryOrgFork() throws Exception {
gitHub.getUser("kohsuke").getRepository("rubywm").forkTo(gitHub.getOrganization("jenkinsci"));
@Test
public void testOrgFork() throws Exception {
kohsuke();
getUser().getRepository("rubywm").forkTo(gitHub.getOrganization("jenkinsci"));
}
public void tryGetTeamsForRepo() throws Exception {
Set<GHTeam> o = gitHub.getOrganization("jenkinsci").getRepository("rubywm").getTeams();
System.out.println(o);
@Test
public void testGetTeamsForRepo() throws Exception {
kohsuke();
assertEquals(1,gitHub.getOrganization("stapler").getRepository("stapler").getTeams().size());
}
@Test
public void testMembership() throws Exception {
Set<String> members = gitHub.getOrganization("jenkinsci").getRepository("violations-plugin").getCollaboratorNames();
System.out.println(members.contains("kohsuke"));
}
@Test
public void testMemberOrgs() throws Exception {
Set<GHOrganization> o = gitHub.getUser("kohsuke").getOrganizations();
System.out.println(o);
}
@Test
public void testCommit() throws Exception {
GHCommit commit = gitHub.getUser("jenkinsci").getRepository("jenkins").getCommit("08c1c9970af4d609ae754fbe803e06186e3206f7");
System.out.println(commit);
@@ -161,6 +272,7 @@ public class AppTest extends TestCase {
assertEquals("changelog.html", f.getFileName());
}
@Test
public void testListCommits() throws Exception {
List<String> sha1 = new ArrayList<String>();
for (GHCommit c : gitHub.getUser("kohsuke").getRepository("empty-commit").listCommits()) {
@@ -171,12 +283,14 @@ public class AppTest extends TestCase {
assertEquals(1,sha1.size());
}
@Test
public void testBranches() throws Exception {
Map<String,GHBranch> b =
gitHub.getUser("jenkinsci").getRepository("jenkins").getBranches();
System.out.println(b);
}
@Test
public void testCommitComment() throws Exception {
GHRepository r = gitHub.getUser("jenkinsci").getRepository("jenkins");
PagedIterable<GHCommitComment> comments = r.listCommitComments();
@@ -187,6 +301,7 @@ public class AppTest extends TestCase {
}
}
@Test
public void testCreateCommitComment() throws Exception {
GHCommit commit = gitHub.getUser("kohsuke").getRepository("sandbox-ant").getCommit("8ae38db0ea5837313ab5f39d43a6f73de3bd9000");
GHCommitComment c = commit.createComment("[testing](http://kohsuse.org/)");
@@ -196,7 +311,9 @@ public class AppTest extends TestCase {
c.delete();
}
@Test
public void tryHook() throws Exception {
kohsuke();
GHRepository r = gitHub.getMyself().getRepository("test2");
GHHook hook = r.createWebHook(new URL("http://www.google.com/"));
System.out.println(hook);
@@ -205,6 +322,7 @@ public class AppTest extends TestCase {
h.delete();
}
@Test
public void testEventApi() throws Exception {
for (GHEventInfo ev : gitHub.getEvents()) {
System.out.println(ev);
@@ -216,6 +334,7 @@ public class AppTest extends TestCase {
}
}
@Test
public void testApp() throws IOException {
System.out.println(gitHub.getMyself().getEmails());
@@ -304,7 +423,9 @@ public class AppTest extends TestCase {
System.out.println(hooks);
}
@Test
public void testOrgRepositories() throws IOException {
kohsuke();
GHOrganization j = gitHub.getOrganization("jenkinsci");
long start = System.currentTimeMillis();
Map<String, GHRepository> repos = j.getRepositories();
@@ -312,7 +433,9 @@ public class AppTest extends TestCase {
System.out.printf("%d repositories in %dms\n",repos.size(),end-start);
}
@Test
public void testOrganization() throws IOException {
kohsuke();
GHOrganization j = gitHub.getOrganization("jenkinsci");
GHTeam t = j.getTeams().get("Core Developers");
@@ -321,18 +444,30 @@ public class AppTest extends TestCase {
// t.add(labs.getRepository("xyz"));
}
@Test
public void testCommitStatus() throws Exception {
GHRepository r = gitHub.getUser("kohsuke").getRepository("test");
GHCommitStatus state;
// state = r.createCommitStatus("edacdd76b06c5f3f0697a22ca75803169f25f296", GHCommitState.FAILURE, "http://jenkins-ci.org/", "oops!");
GHRepository r = gitHub.getRepository("kohsuke/github-api");
List<GHCommitStatus> lst = r.listCommitStatuses("edacdd76b06c5f3f0697a22ca75803169f25f296").asList();
GHCommitStatus state;
// state = r.createCommitStatus("ecbfdd7315ef2cf04b2be7f11a072ce0bd00c396", GHCommitState.FAILURE, "http://kohsuke.org/", "testing!");
List<GHCommitStatus> lst = r.listCommitStatuses("ecbfdd7315ef2cf04b2be7f11a072ce0bd00c396").asList();
state = lst.get(0);
System.out.println(state);
assertEquals("oops!",state.getDescription());
assertEquals("http://jenkins-ci.org/",state.getTargetUrl());
assertEquals("testing!",state.getDescription());
assertEquals("http://kohsuke.org/",state.getTargetUrl());
}
@Test
public void testCommitShortInfo() throws Exception {
GHRepository r = gitHub.getRepository("kohsuke/github-api");
GHCommit commit = r.getCommit("86a2e245aa6d71d54923655066049d9e21a15f23");
assertEquals(commit.getCommitShortInfo().getAuthor().getName(), "Kohsuke Kawaguchi");
assertEquals(commit.getCommitShortInfo().getMessage(), "doc");
}
@Test
public void testPullRequestPopulate() throws Exception {
GHRepository r = gitHub.getUser("kohsuke").getRepository("github-api");
GHPullRequest p = r.getPullRequest(17);
@@ -340,15 +475,21 @@ public class AppTest extends TestCase {
assertNotNull(u.getName());
}
@Test
public void testCheckMembership() throws Exception {
kohsuke();
GHOrganization j = gitHub.getOrganization("jenkinsci");
GHUser kohsuke = gitHub.getUser("kohsuke");
GHUser a = gitHub.getUser("a");
GHUser b = gitHub.getUser("b");
assertTrue(j.hasMember(kohsuke));
assertFalse(j.hasMember(a));
assertFalse(j.hasMember(b));
assertTrue(j.hasPublicMember(kohsuke));
assertFalse(j.hasPublicMember(a));
assertFalse(j.hasPublicMember(b));
}
private void kohsuke() {
Assume.assumeTrue(getUser().getLogin().equals("kohsuke"));
}
}

View File

@@ -0,0 +1,147 @@
package org.kohsuke;
import junit.framework.TestCase;
import org.apache.commons.io.IOUtils;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.kohsuke.github.GHAsset;
import org.kohsuke.github.GHIssue;
import org.kohsuke.github.GHMilestone;
import org.kohsuke.github.GHMyself;
import org.kohsuke.github.GHRelease;
import org.kohsuke.github.GHRepository;
import org.kohsuke.github.GitHub;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Properties;
public class LifecycleTest extends TestCase {
private GitHub gitHub;
@Override
public void setUp() throws Exception {
super.setUp();
gitHub = GitHub.connect();
}
public void testCreateRepository() throws IOException, GitAPIException, InterruptedException {
GHMyself myself = gitHub.getMyself();
GHRepository repository = myself.getRepository("github-api-test");
if (repository != null) {
repository.delete();
Thread.sleep(1000);
}
repository = gitHub.createRepository("github-api-test",
"a test repository used to test kohsuke's github-api", "http://github-api.kohsuke.org/", true);
assertTrue(repository.getReleases().isEmpty());
try {
GHMilestone milestone = repository.createMilestone("Initial Release", "first one");
GHIssue issue = repository.createIssue("Test Issue")
.body("issue body just for grins")
.milestone(milestone)
.assignee(myself)
.label("bug")
.create();
File repoDir = new File(System.getProperty("java.io.tmpdir"), "github-api-test");
delete(repoDir);
Git origin = Git.cloneRepository()
.setBare(false)
.setURI(repository.gitHttpTransportUrl())
.setDirectory(repoDir)
.setCredentialsProvider(getCredentialsProvider(myself))
.call();
commitTestFile(myself, repoDir, origin);
GHRelease release = createRelease(repository);
GHAsset asset = uploadAsset(release);
updateAsset(release, asset);
deleteAsset(release, asset);
} finally {
repository.delete();
}
}
private void updateAsset(GHRelease release, GHAsset asset) throws IOException {
asset.setLabel("test label");
assertEquals("test label", release.getAssets().get(0).getLabel());
}
private void deleteAsset(GHRelease release, GHAsset asset) throws IOException {
asset.delete();
assertEquals(0, release.getAssets().size());
}
private GHAsset uploadAsset(GHRelease release) throws IOException {
GHAsset asset = release.uploadAsset(new File("pom.xml"), "application/text");
assertNotNull(asset);
List<GHAsset> assets = release.getAssets();
assertEquals(1, assets.size());
assertEquals("pom.xml", assets.get(0).getName());
return asset;
}
private GHRelease createRelease(GHRepository repository) throws IOException {
GHRelease builder = repository.createRelease("release_tag")
.name("Test Release")
.body("How exciting! To be able to programmatically create releases is a dream come true!")
.create();
List<GHRelease> releases = repository.getReleases();
assertEquals(1, releases.size());
GHRelease release = releases.get(0);
assertEquals("Test Release", release.getName());
return release;
}
private void commitTestFile(GHMyself myself, File repoDir, Git origin) throws IOException, GitAPIException {
File dummyFile = createDummyFile(repoDir);
DirCache cache = origin.add().addFilepattern(dummyFile.getName()).call();
origin.commit().setMessage("test commit").call();
origin.push().setCredentialsProvider(getCredentialsProvider(myself)).call();
}
private UsernamePasswordCredentialsProvider getCredentialsProvider(GHMyself myself) throws IOException {
Properties props = new Properties();
File homeDir = new File(System.getProperty("user.home"));
FileInputStream in = new FileInputStream(new File(homeDir, ".github"));
try {
props.load(in);
} finally {
IOUtils.closeQuietly(in);
}
return new UsernamePasswordCredentialsProvider(props.getProperty("login"), props.getProperty("oauth"));
}
private void delete(File toDelete) {
if (toDelete.isDirectory()) {
for (File file : toDelete.listFiles()) {
delete(file);
}
}
toDelete.delete();
}
private File createDummyFile(File repoDir) throws IOException {
File file = new File(repoDir, "testFile-" + System.currentTimeMillis());
PrintWriter writer = new PrintWriter(new FileWriter(file));
try {
writer.println("test file");
} finally {
writer.close();
}
return file;
}
}

View File

@@ -0,0 +1,67 @@
package org.kohsuke.github;
import junit.framework.TestCase;
import java.util.List;
import java.util.UUID;
/**
* Integration test for {@link GHContent}.
*/
public class GHContentIntegrationTest extends TestCase {
private GitHub gitHub;
private GHRepository repo;
private String createdFilename;
@Override
public void setUp() throws Exception {
super.setUp();
gitHub = GitHub.connect();
repo = gitHub.getRepository("acollign/github-api-test").fork();
createdFilename = UUID.randomUUID().toString();
}
public void testGetFileContent() throws Exception {
GHContent content = repo.getFileContent("ghcontent-ro/a-file-with-content");
assertTrue(content.isFile());
assertEquals("thanks for reading me\n", content.getContent());
}
public void testGetEmptyFileContent() throws Exception {
GHContent content = repo.getFileContent("ghcontent-ro/an-empty-file");
assertTrue(content.isFile());
assertEquals("", content.getContent());
}
public void testGetDirectoryContent() throws Exception {
List<GHContent> entries = repo.getDirectoryContent("ghcontent-ro/a-dir-with-3-entries");
assertTrue(entries.size() == 3);
}
public void testCRUDContent() throws Exception {
GHContentUpdateResponse created = repo.createContent("this is an awesome file I created\n", "Creating a file for integration tests.", createdFilename);
GHContent createdContent = created.getContent();
assertNotNull(created.getCommit());
assertNotNull(created.getContent());
assertNotNull(createdContent.getContent());
assertEquals("this is an awesome file I created\n", createdContent.getContent());
GHContentUpdateResponse updatedContentResponse = createdContent.update("this is some new content\n", "Updated file for integration tests.");
GHContent updatedContent = updatedContentResponse.getContent();
assertNotNull(updatedContentResponse.getCommit());
assertNotNull(updatedContentResponse.getContent());
assertEquals("this is some new content\n", updatedContent.getContent());
GHContentUpdateResponse deleteResponse = updatedContent.delete("Enough of this foolishness!");
assertNotNull(deleteResponse.getCommit());
assertNull(deleteResponse.getContent());
}
}