Compare commits

...

81 Commits

Author SHA1 Message Date
Kohsuke Kawaguchi
6516b20e16 [maven-release-plugin] prepare release github-api-1.70 2015-08-15 07:19:22 -07:00
Kohsuke Kawaguchi
839cb03690 Overzealous FindBugs changes.
String given without the encoding mandated by a protocol/design/etc should be converted with the platform default encoding. After all it exists for a reason!
2015-08-15 07:17:15 -07:00
Kohsuke Kawaguchi
2bcd99b14f Overzealous findbugs fix.
This method should rely on platform specific encoding
2015-08-14 11:59:55 -07:00
Kohsuke Kawaguchi
e3ebf6e8a1 Merge pull request #212 from umajeric/master
Added option to edit GitHub release once it is created
2015-08-11 09:24:30 +02:00
Uros Majeric
76d28314b0 Added option to edit GitHub release once it is created 2015-08-06 15:40:26 +02:00
Oleg Nenashev
ec450b8fd8 Merge pull request #210 from oleg-nenashev/findbugs-cleanup
Cleanup issues discovered by FindBugs
2015-07-24 15:57:31 +03:00
Oleg Nenashev
79c5b2edd5 FindBugs: Fix over 100 issues and enforce FindBugs 2015-07-20 12:28:41 +03:00
Kohsuke Kawaguchi
2d45ac51ef [maven-release-plugin] prepare for next development iteration 2015-07-17 05:09:28 -07:00
Kohsuke Kawaguchi
505bb8f06d [maven-release-plugin] prepare release github-api-1.69 2015-07-17 05:09:25 -07:00
Kohsuke Kawaguchi
f8408bd29f This method can return null.
I think what's going on is that GitHub takes some non-zero amount of time to compute this value, and our test runs too fast sometimes and try to fetch a PR before its mergeability is computed
2015-07-17 15:06:39 +03:00
Kohsuke Kawaguchi
5f2c84a913 Tests should use test repositories for mutating tests.
Picking up the first random repository you are an owner of and making a change to it is too dangerous.
2015-07-17 14:33:18 +03:00
Kohsuke Kawaguchi
3011c99e3f Merge pull request #208 from oleg-nenashev/master
Fix potential NPE in the code
2015-07-17 14:24:14 +03:00
Oleg Nenashev
ebc97f42ad Fix potential NPE in the code 2015-07-17 14:21:46 +03:00
Kohsuke Kawaguchi
4660c6d363 Merge pull request #192
Changing GHHook to abstract is a binary incompatible change in theory,
but given the way this class is designed it is difficult to imagine
any client code instantiating this class.

So I think it is OK.
2015-07-17 14:06:47 +03:00
Kohsuke Kawaguchi
e239ef50ba Consistent name with other classes 2015-07-17 14:06:35 +03:00
Kohsuke Kawaguchi
8b4312a880 Merge pull request #203 2015-07-17 13:52:35 +03:00
Kohsuke Kawaguchi
90daf8087e Turning this into javadoc so that users can see them in IDE. 2015-07-17 13:52:16 +03:00
Kohsuke Kawaguchi
dd21bcb34c I think this is a better name 2015-07-17 13:51:31 +03:00
Kohsuke Kawaguchi
c4113f1ac7 Merge pull request #182 from henryju/master
Fix invalid URL for pull request comments update/delete
2015-07-17 13:47:43 +03:00
Kohsuke Kawaguchi
efa48acd1d Merge pull request #185 from marc-guenther/master
Fixes #183: added a method listForks() to GHRepository
2015-07-17 13:47:17 +03:00
Kohsuke Kawaguchi
15e4d07a6d Merge pull request #187 from yegorius/master
Recognize previous_file field in GHCommit.File
2015-07-17 13:46:21 +03:00
Kohsuke Kawaguchi
cb2248809c Merge pull request #190 2015-07-17 13:43:01 +03:00
Kohsuke Kawaguchi
eb9551d81b Renamed getMasterBranch to getDefaultBranch
The new set method can be simply renamed without the backward
compatibility version since it's new
2015-07-17 13:42:20 +03:00
Kohsuke Kawaguchi
87d1256a1b Merge pull request #189 from if6was9/fix-post-body-regression
fixed regression that caused POST operations to be sent as GET
2015-07-17 13:39:52 +03:00
Kohsuke Kawaguchi
dd6179cf25 Merge pull request #197 from treeduck/patch-1
added Page Build
2015-07-17 13:35:20 +03:00
Marc Guenther
23c56ff887 remove unused import 2015-07-17 12:30:49 +02:00
Kohsuke Kawaguchi
c4eefa6917 Merge branch 'master' of github.com:kohsuke/github-api 2015-07-17 13:29:40 +03:00
Kohsuke Kawaguchi
202cff58f2 Merge pull request #201 2015-07-17 13:29:22 +03:00
Kohsuke Kawaguchi
025806f0fd Consistent name with other classes 2015-07-17 13:29:07 +03:00
Kohsuke Kawaguchi
b0c54ef0f1 Restored backward compatibility with the former signature 2015-07-17 13:27:20 +03:00
Kohsuke Kawaguchi
4d7681b1a4 Merge pull request #206 from torodev/master
Specified the GET
2015-07-17 13:24:48 +03:00
Kohsuke Kawaguchi
340fb3f624 Merge pull request #207 from oleg-nenashev/findbugs-enable
Enable FindBugs in the repo
2015-07-17 13:13:23 +03:00
Marc Guenther
a83aad22ca renamed Sort enum, some cleanup, better javadoc 2015-07-17 09:33:48 +02:00
Oleg Nenashev
5a418dcce6 Enable FindBugs 2015-07-16 16:56:09 +03:00
torodev
ec5392708f Specified the GET
Previously doesn't specify the HTTP method to perform
2015-07-14 09:47:04 +08:00
Oleg Nenashev
901db92b11 Merge pull request #205 from stephenc/fix-npe
Fix NPE found when resolving issues from search api
2015-07-07 00:22:46 +03:00
Stephen Connolly
01b8b10344 Fix NPE found when resolving issues from search api 2015-07-06 11:07:05 +01:00
Oleg Nenashev
698d642ec8 Merge pull request #204 from lanwen/ping_event
add ping event to GH events enum
2015-07-05 19:57:20 +03:00
MerkushevKirill
90d1047fb2 add ping event to GH events enum 2015-07-05 19:37:56 +03:00
Luca Milanesio
b0d1eac477 GitHub API have changed the semantics of /user/repos API
It seems that since a couple of days (or weeks?) the /user/repos is returning
ALL the repositories that the user has access or collaborates to whilst previously
were only the ones that belong to him.

JavaDoc updated in order to avoid getting unwanted results and introduced as well
the possibility to filter a specific type of repository to be returned:
- All (the GitHub's default)
- Owner (the user's repos)
- Public / Private (public or private repos)
- Member (the user collaborates to)
2015-06-26 13:42:43 +01:00
Julien HENRY
cce02aec3d Add delete and update for GHIssueComment 2015-06-16 09:27:55 +02:00
Julien HENRY
492ff58aa8 Fix invalid URL for pull request comments update/delete 2015-06-16 09:16:49 +02:00
Kohsuke Kawaguchi
dd3e73996b Merge pull request #200 from lanwen/lost_body_write
fix for unused json map when method with body, but body is null
2015-06-15 10:38:14 -07:00
MerkushevKirill
931ed7adac don't ignore args when method without body
in case of GET or DELETE request
2015-06-15 18:14:58 +03:00
MerkushevKirill
861fd55d06 fix for unused json map when method with body, but body is null
fixes regression from b976e0ef4e
2015-06-15 17:57:16 +03:00
Kohsuke Kawaguchi
9a4eee4e7d Merge pull request #198 from lanwen/rate-reset
fix for GH Enterprise which does not have rate limit reset field
2015-06-11 10:53:11 -07:00
MerkushevKirill
ed76cdbddf fix for GH Enterprise which does not have rate limit reset field
Fixes regression from a4c1c8de24
2015-06-11 14:52:50 +03:00
Koji Habu
9d91549803 added Page Build 2015-06-10 15:43:57 -07:00
Marc Guenther
a5425a3c71 improved javadoc for listForks() 2015-05-28 22:18:02 +02:00
Chris Hut
f4b105b10f Enable creation and retrieval of org webhooks
made GHHook abstract and created two concrete subclasses for org
and repo hooks. Created utility class GHHooks to manage creation
and retrieval of org/repo hooks with minimal code duplication. These
are invoked by GHOrganization and GHRepository respectively.
2015-05-15 13:29:18 -07:00
Rob Schoening
e4de09c55b allow default branch to be set 2015-05-09 01:05:04 -07:00
Rob Schoening
d77be9d382 fixed regression that caused POST operations to be sent as GET 2015-05-09 01:01:04 -07:00
yegorius
626909addb recognize previous_file field in GHCommit.File 2015-05-01 17:59:01 +03:00
Marc Guenther
9b750bedef Fixes #183: added a method listForks() to GHRepository
listForks() will list all forks of a repository.
An optional sort argument is also supported.
2015-05-01 14:06:20 +02:00
Kohsuke Kawaguchi
b976e0ef4e Issue #180: don't write body if HTTP method is DELETE. 2015-04-26 10:52:43 -07:00
Kohsuke Kawaguchi
fd434292ad [maven-release-plugin] prepare for next development iteration 2015-04-19 17:40:39 -07:00
Kohsuke Kawaguchi
7b4d3a869b [maven-release-plugin] prepare release github-api-1.68 2015-04-19 17:40:35 -07:00
Kohsuke Kawaguchi
eeebb1b59f Added the 'sha' parameter.
Fixes issue #176
2015-04-19 17:25:13 -07:00
Julien HENRY
63136f64b7 Merge pull request #174
The merge was done manually because the original commit contains lots of
whitespace only changes.
2015-04-19 17:22:04 -07:00
Kohsuke Kawaguchi
1d2fbf2d92 Merge pull request #179 from lskillen/master
Fix NullPointerException on RateLimitHandler when handling API errors.
2015-04-19 17:03:50 -07:00
Kohsuke Kawaguchi
1e52dded14 Added a helper method 2015-04-15 08:33:18 -07:00
Lee Skillen
cfc7005275 Fix NullPointerException on RateLimiter when handling API errors. 2015-04-14 14:45:47 +01:00
Kohsuke Kawaguchi
f23afcd5aa [maven-release-plugin] prepare for next development iteration 2015-04-13 18:30:43 -07:00
Kohsuke Kawaguchi
4e88a0c91b [maven-release-plugin] prepare release github-api-1.67 2015-04-13 18:30:40 -07:00
Kohsuke Kawaguchi
d070f9deb0 TAB -> WS 2015-04-13 18:25:44 -07:00
Kohsuke Kawaguchi
b736e20a74 Added more getHtmlUrl() methods 2015-04-13 18:17:37 -07:00
Kohsuke Kawaguchi
aad20d0a03 Merge pull request #169 from KostyaSha/fixAuthLoop
Throw error for bad creds
2015-04-13 16:55:58 -07:00
Kohsuke Kawaguchi
7ff97348d9 Merge pull request #170 from KostyaSha/coverity
Improvements
2015-04-13 16:55:24 -07:00
Kohsuke Kawaguchi
68dda3a46d Merge pull request #175 2015-04-13 16:47:32 -07:00
Kohsuke Kawaguchi
2cd44f8c33 Added the pair method 2015-04-13 16:47:25 -07:00
Kohsuke Kawaguchi
9775954aff Massaging the PR.
- need to retrieve the object in full to have all the fields properly populated
- documentation fix, as this method points to the root of the forking chain, not just an upstream.
2015-04-13 16:45:38 -07:00
Kohsuke Kawaguchi
1a071b0b54 Returning null instead of throwing an exception (as a matter of taste) 2015-04-13 16:39:20 -07:00
Kohsuke Kawaguchi
8dcea59c74 Fixed javadoc errors 2015-04-13 16:36:14 -07:00
Kohsuke Kawaguchi
f482f77871 Merge pull request #177 from infm/feat/notif
Added getters for the objects notifications refer to
2015-04-13 16:38:22 -07:00
infm
b058c39ee1 Added getters for the objects notifications refer to 2015-04-09 01:21:38 +03:00
Jason Nichols
b926b6c67f Added the source attribute to GHRepository 2015-04-02 14:54:13 -04:00
Kohsuke Kawaguchi
3fb8e5f799 [maven-release-plugin] prepare for next development iteration 2015-03-24 10:26:48 -07:00
Kanstantsin Shautsou
9ebc9c0867 Use FAIL rate-limit handler for tests
Should avoid possible Thread.sleep() for tests execution.
2015-03-23 21:14:42 +03:00
Kanstantsin Shautsou
f1f96713a4 [CID-107552] Unintended regular expression
regex_expected: The . character(s) in the pattern ".md" can match any character, because calls to replaceAll treat the pattern as a regular expression, which might be unexpected.
2015-03-23 02:35:55 +03:00
Kanstantsin Shautsou
fc3b6d2c2e [CID-107535] Missing call to superclass
Similar to other events
2015-03-23 02:23:44 +03:00
Kanstantsin Shautsou
d0d0716b3b Throw error for bad creds 2015-03-23 02:09:23 +03:00
56 changed files with 1704 additions and 699 deletions

31
pom.xml
View File

@@ -7,7 +7,7 @@
</parent>
<artifactId>github-api</artifactId>
<version>1.66</version>
<version>1.70</version>
<name>GitHub API for Java</name>
<url>http://github-api.kohsuke.org/</url>
<description>GitHub API for Java</description>
@@ -16,7 +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>github-api-1.66</tag>
<tag>github-api-1.70</tag>
</scm>
<distributionManagement>
@@ -28,6 +28,8 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<findbugs-maven-plugin.version>3.0.1</findbugs-maven-plugin.version>
<findbugs-maven-plugin.failOnError>true</findbugs-maven-plugin.failOnError>
</properties>
<build>
@@ -44,6 +46,25 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>${findbugs-maven-plugin.version}</version>
<configuration>
<xmlOutput>true</xmlOutput>
<findbugsXmlWithMessages>true</findbugsXmlWithMessages>
<failOnError>${findbugs-maven-plugin.failOnError}</failOnError>
</configuration>
<executions>
<execution>
<id>run-findbugs</id>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
@@ -109,6 +130,12 @@
<version>1.9.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>annotations</artifactId>
<version>3.0.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<repositories>
<repository>

View File

@@ -23,9 +23,13 @@
*/
package org.kohsuke.github;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
/**
* @author Kohsuke Kawaguchi
*/
@SuppressFBWarnings(value = "UUF_UNUSED_PUBLIC_OR_PROTECTED_FIELD",
justification = "Being constructed by JSON deserialization")
class DeleteToken {
public String delete_token;
}

View File

@@ -1,6 +1,7 @@
package org.kohsuke.github;
import java.io.IOException;
import java.net.URL;
/**
* Asset in a release.
@@ -60,6 +61,14 @@ public class GHAsset extends GHObject {
return state;
}
/**
* @deprecated This object has no HTML URL.
*/
@Override
public URL getHtmlUrl() {
return null;
}
public String getBrowserDownloadUrl() {
return browser_download_url;
}

View File

@@ -1,5 +1,6 @@
package org.kohsuke.github;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.net.URL;
import java.util.Collection;
import java.util.Date;
@@ -10,78 +11,86 @@ import java.util.List;
*
* @author janinko
* @see GitHub#createToken(Collection, String, String)
* @see http://developer.github.com/v3/oauth/#create-a-new-authorization
* @see <a href="http://developer.github.com/v3/oauth/#create-a-new-authorization">API documentation</a>
*/
public class GHAuthorization extends GHObject {
public static final String USER = "user";
public static final String USER_EMAIL = "user:email";
public static final String USER_FOLLOW = "user:follow";
public static final String PUBLIC_REPO = "public_repo";
public static final String REPO = "repo";
public static final String REPO_STATUS = "repo:status";
public static final String DELETE_REPO = "delete_repo";
public static final String NOTIFICATIONS = "notifications";
public static final String GIST = "gist";
public static final String READ_HOOK = "read:repo_hook";
public static final String WRITE_HOOK = "write:repo_hook";
public static final String AMIN_HOOK = "admin:repo_hook";
public static final String READ_ORG = "read:org";
public static final String WRITE_ORG = "write:org";
public static final String ADMIN_ORG = "admin:org";
public static final String READ_KEY = "read:public_key";
public static final String WRITE_KEY = "write:public_key";
public static final String ADMIN_KEY = "admin:public_key";
public static final String USER = "user";
public static final String USER_EMAIL = "user:email";
public static final String USER_FOLLOW = "user:follow";
public static final String PUBLIC_REPO = "public_repo";
public static final String REPO = "repo";
public static final String REPO_STATUS = "repo:status";
public static final String DELETE_REPO = "delete_repo";
public static final String NOTIFICATIONS = "notifications";
public static final String GIST = "gist";
public static final String READ_HOOK = "read:repo_hook";
public static final String WRITE_HOOK = "write:repo_hook";
public static final String AMIN_HOOK = "admin:repo_hook";
public static final String READ_ORG = "read:org";
public static final String WRITE_ORG = "write:org";
public static final String ADMIN_ORG = "admin:org";
public static final String READ_KEY = "read:public_key";
public static final String WRITE_KEY = "write:public_key";
public static final String ADMIN_KEY = "admin:public_key";
private GitHub root;
private List<String> scopes;
private String token;
private App app;
private String note;
private String note_url;
private GitHub root;
private List<String> scopes;
private String token;
private App app;
private String note;
private String note_url;
public GitHub getRoot() {
return root;
}
public List<String> getScopes() {
return scopes;
}
public List<String> getScopes() {
return scopes;
}
public String getToken(){
return token;
}
public String getToken() {
return token;
}
public URL getAppUrl(){
public URL getAppUrl() {
return GitHub.parseURL(app.url);
}
}
public String getAppName() {
return app.name;
}
public URL getApiURL(){
public String getAppName() {
return app.name;
}
@SuppressFBWarnings(value = "NM_CONFUSING",
justification = "It's a part of the library API, cannot be changed")
public URL getApiURL() {
return GitHub.parseURL(url);
}
}
public String getNote() {
return note;
}
/**
* @deprecated This object has no HTML URL.
*/
@Override
public URL getHtmlUrl() {
return null;
}
public URL getNoteUrl(){
public String getNote() {
return note;
}
public URL getNoteUrl() {
return GitHub.parseURL(note_url);
}
}
/*package*/ GHAuthorization wrap(GitHub root) {
this.root = root;
return this;
}
/*package*/ GHAuthorization wrap(GitHub root) {
this.root = root;
return this;
}
private static class App{
private String url;
private String name;
}
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD"},
justification = "JSON API")
private static class App {
private String url;
private String name;
}
}

View File

@@ -1,10 +1,14 @@
package org.kohsuke.github;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
/**
* A branch in a repository.
*
* @author Yusuke Kokubo
*/
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
"NP_UNWRITTEN_FIELD"}, justification = "JSON API")
public class GHBranch {
private GitHub root;
private GHRepository owner;
@@ -13,7 +17,10 @@ public class GHBranch {
private Commit commit;
public static class Commit {
String sha,url;
String sha;
@SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now")
String url;
}
public GitHub getRoot() {
@@ -37,10 +44,11 @@ public class GHBranch {
public String getSHA1() {
return commit.sha;
}
@Override
public String toString() {
return "Branch:" + name + " in " + owner.getUrl();
final String url = owner != null ? owner.getUrl().toString() : "unknown";
return "Branch:" + name + " in " + url;
}
/*package*/ GHBranch wrap(GHRepository repo) {

View File

@@ -1,6 +1,7 @@
package org.kohsuke.github;
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.IOException;
import java.net.URL;
@@ -16,6 +17,8 @@ import java.util.List;
* @see GHRepository#getCommit(String)
* @see GHCommitComment#getCommit()
*/
@SuppressFBWarnings(value = {"NP_UNWRITTEN_FIELD", "UWF_UNWRITTEN_FIELD"},
justification = "JSON API")
public class GHCommit {
private GHRepository owner;
@@ -24,6 +27,8 @@ public class GHCommit {
/**
* Short summary of this commit.
*/
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
"NP_UNWRITTEN_FIELD", "UWF_UNWRITTEN_FIELD"}, justification = "JSON API")
public static class ShortInfo {
private GHAuthor author;
private GHAuthor committer;
@@ -32,26 +37,26 @@ public class GHCommit {
private int comment_count;
@WithBridgeMethods(value=GHAuthor.class,castRequired=true)
public GitUser getAuthor() {
return author;
}
@WithBridgeMethods(value = GHAuthor.class, castRequired = true)
public GitUser getAuthor() {
return author;
}
@WithBridgeMethods(value=GHAuthor.class,castRequired=true)
public GitUser getCommitter() {
return committer;
}
@WithBridgeMethods(value = GHAuthor.class, castRequired = true)
public GitUser getCommitter() {
return committer;
}
/**
* Commit message.
*/
public String getMessage() {
return message;
}
public String getMessage() {
return message;
}
public int getCommentCount() {
return comment_count;
}
public int getCommentCount() {
return comment_count;
}
}
/**
@@ -67,10 +72,13 @@ public class GHCommit {
/**
* A file that was modified.
*/
@SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD",
justification = "It's being initilized by JSON deserialization")
public static class File {
String status;
int changes,additions,deletions;
String raw_url, blob_url, filename, sha, patch;
String raw_url, blob_url, sha, patch;
String filename, previous_filename;
/**
* Number of lines added + removed.
@@ -101,12 +109,21 @@ public class GHCommit {
}
/**
* Just the base name and the extension without any directory name.
* Full path in the repository.
*/
@SuppressFBWarnings(value = "NM_CONFUSING",
justification = "It's a part of the library's API and cannot be renamed")
public String getFileName() {
return filename;
}
/**
* Previous path, in case file has moved.
*/
public String getPreviousFilename() {
return previous_filename;
}
/**
* The actual change.
*/
@@ -139,13 +156,19 @@ public class GHCommit {
}
public static class Parent {
String url,sha;
@SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now")
String url;
String sha;
}
static class User {
// TODO: what if someone who doesn't have an account on GitHub makes a commit?
String url,avatar_url,login,gravatar_id;
@SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now")
String url,avatar_url,gravatar_id;
@SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now")
int id;
String login;
}
String url,sha;
@@ -153,14 +176,13 @@ public class GHCommit {
Stats stats;
List<Parent> parents;
User author,committer;
public ShortInfo getCommitShortInfo() {
return commit;
}
return commit;
}
/**
/**
* The repository that contains the commit.
*/
public GHRepository getOwner() {

View File

@@ -1,5 +1,6 @@
package org.kohsuke.github;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.IOException;
import java.net.URL;
import java.util.Date;
@@ -12,6 +13,8 @@ import java.util.Date;
* @see GHCommit#listComments()
* @see GHCommit#createComment(String, String, Integer, Integer)
*/
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
"NP_UNWRITTEN_FIELD"}, justification = "JSON API")
public class GHCommitComment extends GHObject {
private GHRepository owner;
@@ -22,8 +25,12 @@ public class GHCommitComment extends GHObject {
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;
@SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now")
String url,avatar_url,gravatar_id;
@SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now")
int id;
String login;
}
public GHRepository getOwner() {
@@ -83,7 +90,7 @@ public class GHCommitComment extends GHObject {
* Updates the body of the commit message.
*/
public void update(String body) throws IOException {
GHCommitComment r = new Requester(owner.root)
new Requester(owner.root)
.with("body", body)
.method("PATCH").to(getApiTail(), GHCommitComment.class);
this.body = body;

View File

@@ -23,6 +23,8 @@
*/
package org.kohsuke.github;
import java.io.IOException;
/**
* Identifies a commit in {@link GHPullRequest}.
*
@@ -69,6 +71,13 @@ public class GHCommitPointer {
return label;
}
/**
* Obtains the commit that this pointer is referring to.
*/
public GHCommit getCommit() throws IOException {
return getRepository().getCommit(getSha());
}
void wrapUp(GitHub root) {
if (user!=null) user.root = root;
if (repo!=null) repo.wrap(root);

View File

@@ -1,14 +1,15 @@
package org.kohsuke.github;
import java.io.IOException;
import java.net.URL;
import java.util.Date;
/**
* Represents a status of a commit.
*
* @author Kohsuke Kawaguchi
* @see GHRepository#getCommitStatus(String)
* @see GHCommit#getStatus()
* @see GHRepository#getLastCommitStatus(String)
* @see GHCommit#getLastStatus()
*/
public class GHCommitStatus extends GHObject {
String state;
@@ -49,7 +50,15 @@ public class GHCommitStatus extends GHObject {
return creator;
}
public String getContext() {
return context;
}
public String getContext() {
return context;
}
/**
* @deprecated This object has no HTML URL.
*/
@Override
public URL getHtmlUrl() {
return null;
}
}

View File

@@ -1,8 +1,10 @@
package org.kohsuke.github;
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.net.URL;
import java.util.Arrays;
import java.util.Date;
/**
@@ -65,15 +67,23 @@ public class GHCompare {
return merge_base_commit;
}
/**
* Gets an array of commits.
* @return A copy of the array being stored in the class.
*/
public Commit[] getCommits() {
return commits;
return Arrays.copyOf(commits, commits.length);
}
/**
* Gets an array of commits.
* @return A copy of the array being stored in the class.
*/
public GHCommit.File[] getFiles() {
return files;
}
return Arrays.copyOf(files, files.length);
}
public GHCompare wrap(GHRepository owner) {
public GHCompare wrap(GHRepository owner) {
this.owner = owner;
for (Commit commit : commits) {
commit.wrapUp(owner);
@@ -87,6 +97,8 @@ public class GHCompare {
* Compare commits had a child commit element with additional details we want to capture.
* This extenstion of GHCommit provides that.
*/
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD"},
justification = "JSON API")
public static class Commit extends GHCommit {
private InnerCommit commit;

View File

@@ -1,5 +1,6 @@
package org.kohsuke.github;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
@@ -75,6 +76,7 @@ public class GHContent {
* @deprecated
* Use {@link #read()}
*/
@SuppressFBWarnings("DM_DEFAULT_ENCODING")
public String getContent() throws IOException {
return new String(DatatypeConverter.parseBase64Binary(getEncodedContent()));
}
@@ -161,10 +163,12 @@ public class GHContent {
};
}
@SuppressFBWarnings("DM_DEFAULT_ENCODING")
public GHContentUpdateResponse update(String newContent, String commitMessage) throws IOException {
return update(newContent.getBytes(), commitMessage, null);
}
@SuppressFBWarnings("DM_DEFAULT_ENCODING")
public GHContentUpdateResponse update(String newContent, String commitMessage, String branch) throws IOException {
return update(newContent.getBytes(), commitMessage, branch);
}

View File

@@ -9,7 +9,7 @@ public class GHDeployKey {
protected String url, key, title;
protected boolean verified;
protected int id;
private GHRepository owner;
private GHRepository owner;
public int getId() {
return id;
@@ -31,10 +31,10 @@ public class GHDeployKey {
return verified;
}
public GHDeployKey wrap(GHRepository repo) {
this.owner = repo;
return this;
}
public GHDeployKey wrap(GHRepository repo) {
this.owner = repo;
return this;
}
public String toString() {
return new ToStringBuilder(this).append("title",title).append("id",id).append("key",key).toString();

View File

@@ -50,4 +50,12 @@ public class GHDeployment extends GHObject {
public String getSha(){
return sha;
}
/**
* @deprecated This object has no HTML URL.
*/
@Override
public URL getHtmlUrl() {
return null;
}
}

View File

@@ -1,6 +1,7 @@
package org.kohsuke.github;
import java.net.URL;
import java.util.Locale;
public class GHDeploymentStatus extends GHObject {
private GHRepository owner;
@@ -28,9 +29,16 @@ public class GHDeploymentStatus extends GHObject {
public URL getRepositoryUrl() {
return GitHub.parseURL(repository_url);
}
public GHDeploymentState getState() {
return GHDeploymentState.valueOf(state.toUpperCase());
return GHDeploymentState.valueOf(state.toUpperCase(Locale.ENGLISH));
}
/**
* @deprecated This object has no HTML URL.
*/
@Override
public URL getHtmlUrl() {
return null;
}
}

View File

@@ -1,6 +1,7 @@
package org.kohsuke.github;
import java.io.IOException;
import java.util.Locale;
public class GHDeploymentStatusBuilder {
private final Requester builder;
@@ -11,7 +12,7 @@ public class GHDeploymentStatusBuilder {
this.repo = repo;
this.deploymentId = deploymentId;
this.builder = new Requester(repo.root);
this.builder.with("state",state.toString().toLowerCase());
this.builder.with("state",state.toString().toLowerCase(Locale.ENGLISH));
}
public GHDeploymentStatusBuilder description(String description) {

View File

@@ -23,12 +23,16 @@
*/
package org.kohsuke.github;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
/**
* Represents an email of GitHub.
*
* @author Kelly Campbell
*/
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
"NP_UNWRITTEN_FIELD", "NP_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD"}, justification = "JSON API")
public class GHEmail {
protected String email;

View File

@@ -23,12 +23,15 @@ public enum GHEvent {
ISSUE_COMMENT,
ISSUES,
MEMBER,
PAGE_BUILD,
PUBLIC,
PULL_REQUEST,
PULL_REQUEST_REVIEW_COMMENT,
PUSH,
RELEASE,
REPOSITORY, // only valid for org hooks
STATUS,
TEAM_ADD,
WATCH
WATCH,
PING
}

View File

@@ -4,12 +4,14 @@ import java.io.IOException;
import java.util.Date;
import com.fasterxml.jackson.databind.node.ObjectNode;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
/**
* Represents an event.
*
* @author Kohsuke Kawaguchi
*/
@SuppressFBWarnings(value = "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", justification = "JSON API")
public class GHEventInfo {
private GitHub root;
@@ -27,8 +29,12 @@ public class GHEventInfo {
/**
* Inside the event JSON model, GitHub uses a slightly different format.
*/
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR" }, justification = "JSON API")
public static class GHEventRepository {
@SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now")
private int id;
@SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now")
private String url; // repository API URL
private String name; // owner/repo
}
@@ -55,10 +61,14 @@ public class GHEventInfo {
/**
* Repository where the change was made.
*/
@SuppressFBWarnings(value = {"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR" },
justification = "The field comes from JSON deserialization")
public GHRepository getRepository() throws IOException {
return root.getRepository(repo.name);
}
@SuppressFBWarnings(value = {"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR" },
justification = "The field comes from JSON deserialization")
public GHUser getActor() throws IOException {
return root.getUser(actor.getLogin());
}
@@ -70,6 +80,8 @@ public class GHEventInfo {
return actor.getLogin();
}
@SuppressFBWarnings(value = {"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR" },
justification = "The field comes from JSON deserialization")
public GHOrganization getOrganization() throws IOException {
return (org==null || org.getLogin()==null) ? null : root.getOrganization(org.getLogin());
}

View File

@@ -1,5 +1,6 @@
package org.kohsuke.github;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.Reader;
import java.util.List;
@@ -25,6 +26,8 @@ public abstract class GHEventPayload {
*
* @see <a href="http://developer.github.com/v3/activity/events/types/#pullrequestevent">authoritative source</a>
*/
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
"NP_UNWRITTEN_FIELD"}, justification = "JSON API")
public static class PullRequest extends GHEventPayload {
private String action;
private int number;
@@ -67,12 +70,15 @@ public abstract class GHEventPayload {
*
* @see <a href="http://developer.github.com/v3/activity/events/types/#issuecommentevent">authoritative source</a>
*/
@SuppressFBWarnings(value = {"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR", "NP_UNWRITTEN_FIELD" },
justification = "Constructed by JSON deserialization")
public static class IssueComment extends GHEventPayload {
private String action;
private GHIssueComment comment;
private GHIssue issue;
private GHRepository repository;
@SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Comes from JSON deserialization")
public String getAction() {
return action;
}
@@ -104,8 +110,12 @@ public abstract class GHEventPayload {
@Override
void wrapUp(GitHub root) {
super.wrapUp(root);
repository.wrap(root);
issue.wrap(repository);
if (repository != null) {
repository.wrap(root);
issue.wrap(repository);
} else {
issue.wrap(root);
}
comment.wrapUp(issue);
}
}
@@ -165,6 +175,7 @@ public abstract class GHEventPayload {
@Override
void wrapUp(GitHub root) {
super.wrapUp(root);
if (repository!=null)
repository.wrap(root);
}

View File

@@ -3,6 +3,7 @@ package org.kohsuke.github;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.io.IOException;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -60,8 +61,8 @@ public class GHGist extends GHObject {
return git_push_url;
}
public String getHtmlUrl() {
return html_url;
public URL getHtmlUrl() {
return GitHub.parseURL(html_url);
}
public boolean isPublic() {

View File

@@ -1,6 +1,8 @@
package org.kohsuke.github;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.IOException;
import java.net.URL;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
@@ -10,22 +12,14 @@ import java.util.Map;
/**
* @author Kohsuke Kawaguchi
*/
public class GHHook extends GHObject {
/**
* Repository that the hook belongs to.
*/
/*package*/ transient GHRepository repository;
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
"NP_UNWRITTEN_FIELD"}, justification = "JSON API")
public abstract class GHHook extends GHObject {
String name;
List<String> events;
boolean active;
Map<String,String> config;
/*package*/ GHHook wrap(GHRepository owner) {
this.repository = owner;
return this;
}
public String getName() {
return name;
}
@@ -49,6 +43,18 @@ public class GHHook extends GHObject {
* Deletes this hook.
*/
public void delete() throws IOException {
new Requester(repository.root).method("DELETE").to(String.format("/repos/%s/%s/hooks/%d", repository.getOwnerName(), repository.getName(), id));
new Requester(getRoot()).method("DELETE").to(getApiRoute());
}
/**
* @deprecated This object has no HTML URL.
*/
@Override
public URL getHtmlUrl() {
return null;
}
abstract GitHub getRoot();
abstract String getApiRoute();
}

View File

@@ -0,0 +1,130 @@
package org.kohsuke.github;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Map;
/**
* Utility class for creating and retrieving webhooks; removes duplication between GHOrganization and GHRepository
* functionality
*/
class GHHooks {
static abstract class Context {
private final GitHub root;
private Context(GitHub root) {
this.root = root;
}
public List<GHHook> getHooks() throws IOException {
List<GHHook> list = new ArrayList<GHHook>(Arrays.asList(
root.retrieve().to(collection(), collectionClass())));
for (GHHook h : list)
wrap(h);
return list;
}
public GHHook getHook(int id) throws IOException {
GHHook hook = root.retrieve().to(collection() + "/" + id, clazz());
return wrap(hook);
}
public GHHook createHook(String name, Map<String, String> config, Collection<GHEvent> events, boolean active) throws IOException {
List<String> ea = null;
if (events!=null) {
ea = new ArrayList<String>();
for (GHEvent e : events)
ea.add(e.name().toLowerCase(Locale.ENGLISH));
}
GHHook hook = new Requester(root)
.with("name", name)
.with("active", active)
._with("config", config)
._with("events", ea)
.to(collection(), clazz());
return wrap(hook);
}
abstract String collection();
abstract Class<? extends GHHook[]> collectionClass();
abstract Class<? extends GHHook> clazz();
abstract GHHook wrap(GHHook hook);
}
private static class RepoContext extends Context {
private final GHRepository repository;
private final GHUser owner;
private RepoContext(GHRepository repository, GHUser owner) {
super(repository.root);
this.repository = repository;
this.owner = owner;
}
@Override
String collection() {
return String.format("/repos/%s/%s/hooks", owner.getLogin(), repository.getName());
}
@Override
Class<? extends GHHook[]> collectionClass() {
return GHRepoHook[].class;
}
@Override
Class<? extends GHHook> clazz() {
return GHRepoHook.class;
}
@Override
GHHook wrap(GHHook hook) {
return ((GHRepoHook)hook).wrap(repository);
}
}
private static class OrgContext extends Context {
private final GHOrganization organization;
private OrgContext(GHOrganization organization) {
super(organization.root);
this.organization = organization;
}
@Override
String collection() {
return String.format("/orgs/%s/hooks", organization.getLogin());
}
@Override
Class<? extends GHHook[]> collectionClass() {
return GHOrgHook[].class;
}
@Override
Class<? extends GHHook> clazz() {
return GHOrgHook.class;
}
@Override
GHHook wrap(GHHook hook) {
return ((GHOrgHook)hook).wrap(organization);
}
}
static Context repoContext(GHRepository repository, GHUser owner) {
return new RepoContext(repository, owner);
}
static Context orgContext(GHOrganization organization) {
return new OrgContext(organization);
}
}

View File

@@ -24,6 +24,9 @@
package org.kohsuke.github;
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.IOException;
import java.net.URL;
import java.util.Collection;
@@ -44,8 +47,8 @@ import java.util.Locale;
public class GHIssue extends GHObject {
GitHub root;
GHRepository owner;
// API v3
// API v3
protected GHUser assignee;
protected String state;
protected int number;
@@ -74,9 +77,9 @@ public class GHIssue extends GHObject {
/*package*/ GHIssue wrap(GitHub root) {
this.root = root;
if(assignee != null) assignee.wrapUp(root);
if(user != null) user.wrapUp(root);
if(closed_by != null) closed_by.wrapUp(root);
if(assignee != null) assignee.wrapUp(root);
if(user != null) user.wrapUp(root);
if(closed_by != null) closed_by.wrapUp(root);
return this;
}
@@ -134,15 +137,20 @@ public class GHIssue extends GHObject {
return GitHub.parseDate(closed_at);
}
public URL getApiURL(){
public URL getApiURL(){
return GitHub.parseURL(url);
}
}
/**
* Updates the issue by adding a comment.
*
* @return
* Newly posted comment.
*/
public void comment(String message) throws IOException {
new Requester(root).with("body",message).to(getIssuesApiRoute() + "/comments");
@WithBridgeMethods(void.class)
public GHIssueComment comment(String message) throws IOException {
GHIssueComment r = new Requester(root).with("body",message).to(getIssuesApiRoute() + "/comments", GHIssueComment.class);
return r.wrapUp(this);
}
private void edit(String key, Object value) throws IOException {
@@ -176,7 +184,7 @@ public class GHIssue extends GHObject {
}
public void assignTo(GHUser user) throws IOException {
editIssue("assignee",user.getLogin());
editIssue("assignee", user.getLogin());
}
public void setLabels(String... labels) throws IOException {
@@ -185,16 +193,16 @@ public class GHIssue extends GHObject {
/**
* Obtains all the comments associated with this issue.
*
* @see #listComments()
*
* @see #listComments()
*/
public List<GHIssueComment> getComments() throws IOException {
return listComments().asList();
}
/**
* Obtains all the comments associated with this issue.
*/
public List<GHIssueComment> getComments() throws IOException {
return listComments().asList();
}
/**
* Obtains all the comments associated with this issue.
*/
public PagedIterable<GHIssueComment> listComments() throws IOException {
return new PagedIterable<GHIssueComment>() {
public PagedIterator<GHIssueComment> iterator() {
@@ -216,16 +224,16 @@ public class GHIssue extends GHObject {
return "/repos/"+owner.getOwnerName()+"/"+owner.getName()+"/issues/"+number;
}
public GHUser getAssignee() {
return assignee;
}
public GHUser getAssignee() {
return assignee;
}
/**
* User who submitted the issue.
*/
public GHUser getUser() {
public GHUser getUser() {
return user;
}
}
/**
* Reports who has closed the issue.
@@ -235,46 +243,48 @@ public class GHIssue extends GHObject {
* even for an issue that's already closed. See
* https://github.com/kohsuke/github-api/issues/60.
*/
public GHUser getClosedBy() {
if(!"closed".equals(state)) return null;
if(closed_by != null) return closed_by;
//TODO closed_by = owner.getIssue(number).getClosed_by();
return closed_by;
}
public int getCommentsCount(){
return comments;
}
public GHUser getClosedBy() {
if(!"closed".equals(state)) return null;
if(closed_by != null) return closed_by;
//TODO closed_by = owner.getIssue(number).getClosed_by();
return closed_by;
}
public int getCommentsCount(){
return comments;
}
/**
* Returns non-null if this issue is a shadow of a pull request.
*/
public PullRequest getPullRequest() {
return pull_request;
}
public PullRequest getPullRequest() {
return pull_request;
}
public boolean isPullRequest() {
return pull_request!=null;
}
public GHMilestone getMilestone() {
return milestone;
}
public GHMilestone getMilestone() {
return milestone;
}
public static class PullRequest{
private String diff_url, patch_url, html_url;
public URL getDiffUrl() {
return GitHub.parseURL(diff_url);
}
public URL getPatchUrl() {
return GitHub.parseURL(patch_url);
}
public URL getUrl() {
return GitHub.parseURL(html_url);
}
}
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD"},
justification = "JSON API")
public static class PullRequest{
private String diff_url, patch_url, html_url;
public URL getDiffUrl() {
return GitHub.parseURL(diff_url);
}
public URL getPatchUrl() {
return GitHub.parseURL(patch_url);
}
public URL getUrl() {
return GitHub.parseURL(html_url);
}
}
}

View File

@@ -25,7 +25,6 @@ package org.kohsuke.github;
import java.io.IOException;
import java.net.URL;
import java.util.Date;
/**
* Comment to the issue
@@ -71,4 +70,31 @@ public class GHIssueComment extends GHObject {
public GHUser getUser() throws IOException {
return owner.root.getUser(user.getLogin());
}
/**
* @deprecated This object has no HTML URL.
*/
@Override
public URL getHtmlUrl() {
return null;
}
/**
* Updates the body of the issue comment.
*/
public void update(String body) throws IOException {
new Requester(owner.root).with("body", body).method("PATCH").to(getApiRoute(), GHIssueComment.class);
this.body = body;
}
/**
* Deletes this issue comment.
*/
public void delete() throws IOException {
new Requester(owner.root).method("DELETE").to(getApiRoute());
}
private String getApiRoute() {
return "/repos/"+owner.getRepository().getOwnerName()+"/"+owner.getRepository().getName()+"/issues/comments/" + id;
}
}

View File

@@ -1,5 +1,6 @@
package org.kohsuke.github;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import org.apache.commons.lang.builder.ToStringBuilder;
/**
@@ -7,6 +8,7 @@ import org.apache.commons.lang.builder.ToStringBuilder;
*
* @author Kohsuke Kawaguchi
*/
@SuppressFBWarnings(value = "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", justification = "JSON API")
public class GHKey {
/*package almost final*/ GitHub root;
@@ -33,6 +35,10 @@ public class GHKey {
return url;
}
public GitHub getRoot() {
return root;
}
public boolean isVerified() {
return verified;
}

View File

@@ -1,6 +1,7 @@
package org.kohsuke.github;
import java.io.IOException;
import java.net.URL;
import java.util.Date;
import java.util.Locale;
@@ -11,52 +12,56 @@ import java.util.Locale;
*/
public class GHMilestone extends GHObject {
GitHub root;
GHRepository owner;
GHRepository owner;
GHUser creator;
private String state, due_on, title, description;
private int closed_issues, open_issues, number;
GHUser creator;
private String state, due_on, title, description, html_url;
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 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 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 getDescription() {
return description;
}
public int getClosedIssues() {
return closed_issues;
}
public int getOpenIssues() {
return open_issues;
}
public int getNumber() {
return number;
}
public URL getHtmlUrl() {
return GitHub.parseURL(html_url);
}
public GHMilestoneState getState() {
return Enum.valueOf(GHMilestoneState.class, state.toUpperCase(Locale.ENGLISH));
}
/**
* Closes this issue.
@@ -73,9 +78,9 @@ public class GHMilestone extends GHObject {
return "/repos/"+owner.getOwnerName()+"/"+owner.getName()+"/milestones/"+number;
}
public GHMilestone wrap(GHRepository repo) {
this.owner = repo;
this.root = repo.root;
return this;
}
public GHMilestone wrap(GHRepository repo) {
this.owner = repo;
this.root = repo.root;
return this;
}
}

View File

@@ -5,8 +5,8 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
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;
@@ -17,6 +17,33 @@ import java.util.TreeMap;
* @author Kohsuke Kawaguchi
*/
public class GHMyself extends GHUser {
/**
* Type of repositories returned during listing.
*/
public enum RepositoryListFilter {
/**
* All public and private repositories that current user has access or collaborates to
*/
ALL,
/**
* Public and private repositories owned by current user
*/
OWNER,
/**
* Public repositories that current user has access or collaborates to
*/
PUBLIC,
/**
* Private repositories that current user has access or collaborates to
*/
PRIVATE,
/**
* Public and private repositories that current user is a member
*/
MEMBER;
}
/**
* @deprecated
* Use {@link #getEmails2()}
@@ -109,16 +136,31 @@ public class GHMyself extends GHUser {
}
/**
* Lists up all the repositories this user owns (public and private) using the specified page size.
* List repositories that are accessible to the authenticated user (public and private) using the specified page size.
*
* This includes repositories owned by the authenticated user, repositories that belong to other users
* where the authenticated user is a collaborator, and other organizations' repositories that the authenticated
* user has access to through an organization membership.
*
* @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 listRepositories(pageSize, RepositoryListFilter.ALL);
}
/**
* List repositories of a certain type that are accessible by current authenticated user using the specified page size.
*
* @param pageSize size for each page of items returned by GitHub. Maximum page size is 100.
* @param repoType type of repository returned in the listing
*/
public PagedIterable<GHRepository> listRepositories(final int pageSize, final RepositoryListFilter repoType) {
return new PagedIterable<GHRepository>() {
public PagedIterator<GHRepository> iterator() {
return new PagedIterator<GHRepository>(root.retrieve().asIterator("/user/repos?per_page=" + pageSize, GHRepository[].class)) {
return new PagedIterator<GHRepository>(root.retrieve().asIterator("/user/repos?per_page=" + pageSize +
"&type=" + repoType.name().toLowerCase(Locale.ENGLISH), GHRepository[].class)) {
@Override
protected void wrapUp(GHRepository[] page) {
for (GHRepository c : page)

View File

@@ -152,7 +152,7 @@ public class GHNotificationStream implements Iterable<GHThread> {
while (true) {
long now = System.currentTimeMillis();
if (nextCheckTime < now) break;
long waitTime = Math.max(Math.min(nextCheckTime - now, 1000), 60 * 1000);
long waitTime = Math.min(Math.max(nextCheckTime - now, 1000), 60 * 1000);
Thread.sleep(waitTime);
}
@@ -180,7 +180,8 @@ public class GHNotificationStream implements Iterable<GHThread> {
private long calcNextCheckTime() {
String v = req.getResponseHeader("X-Poll-Interval");
if (v==null) v="60";
return System.currentTimeMillis()+Integer.parseInt(v)*1000;
long seconds = Integer.parseInt(v);
return System.currentTimeMillis() + seconds*1000;
}
public void remove() {

View File

@@ -1,6 +1,7 @@
package org.kohsuke.github;
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.IOException;
import java.net.URL;
@@ -9,6 +10,8 @@ import java.util.Date;
/**
* Most (all?) domain objects in GitHub seems to have these 4 properties.
*/
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
"NP_UNWRITTEN_FIELD"}, justification = "JSON API")
public abstract class GHObject {
protected String url;
protected int id;
@@ -26,10 +29,6 @@ public abstract class GHObject {
return GitHub.parseDate(created_at);
}
private Object createdAtStr(Date id, Class type) {
return created_at;
}
/**
* API URL of this object.
*/
@@ -38,6 +37,12 @@ public abstract class GHObject {
return GitHub.parseURL(url);
}
/**
* URL of this object for humans, which renders some HTML.
*/
@WithBridgeMethods(value=String.class, adapterMethod="urlToString")
public abstract URL getHtmlUrl();
/**
* When was this resource last updated?
*/
@@ -52,12 +57,4 @@ public abstract class GHObject {
public int getId() {
return id;
}
private Object intToString(int id, Class type) {
return String.valueOf(id);
}
private Object urlToString(URL url, Class type) {
return url==null ? null : url.toString();
}
}

View File

@@ -0,0 +1,27 @@
/*
* © Copyright 2015 - SourceClear Inc
*/
package org.kohsuke.github;
class GHOrgHook extends GHHook {
/**
* Organization that the hook belongs to.
*/
/*package*/ transient GHOrganization organization;
/*package*/ GHOrgHook wrap(GHOrganization owner) {
this.organization = owner;
return this;
}
@Override
GitHub getRoot() {
return organization.root;
}
@Override
String getApiRoute() {
return String.format("/orgs/%s/hooks/%d", organization.getLogin(), id);
}
}

View File

@@ -1,10 +1,13 @@
package org.kohsuke.github;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
@@ -26,7 +29,7 @@ public class GHOrganization extends GHPerson {
GHTeam t = getTeams().get(team);
if (t==null)
throw new IllegalArgumentException("No such team: "+team);
return createRepository(name,description,homepage,t,isPublic);
return createRepository(name, description, homepage, t, isPublic);
}
public GHRepository createRepository(String name, String description, String homepage, GHTeam team, boolean isPublic) throws IOException {
@@ -172,7 +175,7 @@ public class GHOrganization extends GHPerson {
* Creates a new team and assigns the repositories.
*/
public GHTeam createTeam(String name, Permission p, Collection<GHRepository> repositories) throws IOException {
Requester post = new Requester(root).with("name", name).with("permission", p.name().toLowerCase());
Requester post = new Requester(root).with("name", name).with("permission", p.name().toLowerCase(Locale.ENGLISH));
List<String> repo_names = new ArrayList<String>();
for (GHRepository r : repositories) {
repo_names.add(r.getName());
@@ -252,4 +255,39 @@ public class GHOrganization extends GHPerson {
}
};
}
/**
* Retrieves the currently configured hooks.
*/
public List<GHHook> getHooks() throws IOException {
return GHHooks.orgContext(this).getHooks();
}
public GHHook getHook(int id) throws IOException {
return GHHooks.orgContext(this).getHook(id);
}
/**
*
* 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. See https://api.github.com/hooks for possible names.
* @param config
* The configuration hash.
* @param events
* Can be null. Types of events to hook into.
*/
public GHHook createHook(String name, Map<String,String> config, Collection<GHEvent> events, boolean active) throws IOException {
return GHHooks.orgContext(this).createHook(name, config, events, active);
}
public GHHook createWebHook(URL url, Collection<GHEvent> events) throws IOException {
return createHook("web", Collections.singletonMap("url", url.toExternalForm()),events,true);
}
public GHHook createWebHook(URL url) throws IOException {
return createWebHook(url, null);
}
}

View File

@@ -2,6 +2,7 @@ package org.kohsuke.github;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
@@ -214,8 +215,9 @@ public abstract class GHPerson extends GHObject {
return blog;
}
public String getHtmlUrl() {
return html_url;
@Override
public URL getHtmlUrl() {
return GitHub.parseURL(html_url);
}
/**

View File

@@ -10,6 +10,8 @@ import java.util.HashSet;
* @author Kohsuke Kawaguchi
*/
public class GHPersonSet<T extends GHPerson> extends HashSet<T> {
private static final long serialVersionUID = 1L;
public GHPersonSet() {
}

View File

@@ -27,7 +27,6 @@ import java.io.IOException;
import java.net.URL;
import java.util.Collection;
import java.util.Date;
import java.util.Locale;
/**
* A pull request.
@@ -37,20 +36,20 @@ import java.util.Locale;
*/
@SuppressWarnings({"UnusedDeclaration"})
public class GHPullRequest extends GHIssue {
private String patch_url, diff_url, issue_url;
private GHCommitPointer base;
private String merged_at;
private GHCommitPointer head;
private String patch_url, diff_url, issue_url;
private GHCommitPointer base;
private String merged_at;
private GHCommitPointer head;
// details that are only available when obtained from ID
private GHUser merged_by;
private int review_comments, additions;
private boolean merged;
private Boolean mergeable;
private int deletions;
private String mergeable_state;
private int changed_files;
private int review_comments, additions;
private boolean merged;
private Boolean mergeable;
private int deletions;
private String mergeable_state;
private int changed_files;
/**
* GitHub doesn't return some properties of {@link GHIssue} when requesting the GET on the 'pulls' API
@@ -60,15 +59,15 @@ public class GHPullRequest extends GHIssue {
private transient boolean fetchedIssueDetails;
GHPullRequest wrapUp(GHRepository owner) {
this.wrap(owner);
GHPullRequest wrapUp(GHRepository owner) {
this.wrap(owner);
return wrapUp(owner.root);
}
GHPullRequest wrapUp(GitHub root) {
if (owner!=null) owner.wrap(root);
if (base!=null) base.wrapUp(root);
if (head!=null) head.wrapUp(root);
if (owner != null) owner.wrap(root);
if (base != null) base.wrapUp(root);
if (head != null) head.wrapUp(root);
if (merged_by != null) merged_by.wrapUp(root);
return this;
}
@@ -85,8 +84,8 @@ public class GHPullRequest extends GHIssue {
public URL getPatchUrl() {
return GitHub.parseURL(patch_url);
}
/**
/**
* The URL of the patch file.
* like https://github.com/jenkinsci/jenkins/pull/100.patch
*/
@@ -108,8 +107,8 @@ public class GHPullRequest extends GHIssue {
public GHCommitPointer getHead() {
return head;
}
@Deprecated
@Deprecated
public Date getIssueUpdatedAt() throws IOException {
return super.getUpdatedAt();
}
@@ -126,65 +125,65 @@ public class GHPullRequest extends GHIssue {
return GitHub.parseDate(merged_at);
}
@Override
public Collection<GHLabel> getLabels() throws IOException {
@Override
public Collection<GHLabel> getLabels() throws IOException {
fetchIssue();
return super.getLabels();
}
return super.getLabels();
}
@Override
public GHUser getClosedBy() {
return null;
}
public GHUser getClosedBy() {
return null;
}
@Override
public PullRequest getPullRequest() {
return null;
}
@Override
public PullRequest getPullRequest() {
return null;
}
//
//
// details that are only available via get with ID
//
//
public GHUser getMergedBy() throws IOException {
populate();
return merged_by;
}
return merged_by;
}
public int getReviewComments() throws IOException {
public int getReviewComments() throws IOException {
populate();
return review_comments;
}
return review_comments;
}
public int getAdditions() throws IOException {
public int getAdditions() throws IOException {
populate();
return additions;
}
return additions;
}
public boolean isMerged() throws IOException {
populate();
return merged;
}
return merged;
}
public Boolean getMergeable() throws IOException {
public Boolean getMergeable() throws IOException {
populate();
return mergeable;
}
return mergeable;
}
public int getDeletions() throws IOException {
public int getDeletions() throws IOException {
populate();
return deletions;
}
return deletions;
}
public String getMergeableState() throws IOException {
public String getMergeableState() throws IOException {
populate();
return mergeable_state;
}
return mergeable_state;
}
public int getChangedFiles() throws IOException {
public int getChangedFiles() throws IOException {
populate();
return changed_files;
}
return changed_files;
}
/**
* Fully populate the data by retrieving missing data.
@@ -197,6 +196,39 @@ public class GHPullRequest extends GHIssue {
root.retrieve().to(url, this).wrapUp(owner);
}
/**
* Retrieves all the commits associated to this pull request.
*/
public PagedIterable<GHPullRequestFileDetail> listFiles() {
return new PagedIterable<GHPullRequestFileDetail>() {
public PagedIterator<GHPullRequestFileDetail> iterator() {
return new PagedIterator<GHPullRequestFileDetail>(root.retrieve().asIterator(String.format("%s/files", getApiURL()),
GHPullRequestFileDetail[].class)) {
@Override
protected void wrapUp(GHPullRequestFileDetail[] page) {
}
};
}
};
}
/**
* Obtains all the review comments associated with this pull request.
*/
public PagedIterable<GHPullRequestReviewComment> listReviewComments() throws IOException {
return new PagedIterable<GHPullRequestReviewComment>() {
public PagedIterator<GHPullRequestReviewComment> iterator() {
return new PagedIterator<GHPullRequestReviewComment>(root.retrieve().asIterator(getApiRoute() + "/comments",
GHPullRequestReviewComment[].class)) {
protected void wrapUp(GHPullRequestReviewComment[] page) {
for (GHPullRequestReviewComment c : page)
c.wrapUp(GHPullRequest.this);
}
};
}
};
}
/**
* Retrieves all the commits associated to this pull request.
*/
@@ -208,12 +240,23 @@ public class GHPullRequest extends GHIssue {
GHPullRequestCommitDetail[].class)) {
@Override
protected void wrapUp(GHPullRequestCommitDetail[] page) {
for (GHPullRequestCommitDetail c : page)
c.wrapUp(GHPullRequest.this);
}
};
}
};
}
public GHPullRequestReviewComment createReviewComment(String body, String sha, String path, int position) throws IOException {
return new Requester(root).method("POST")
.with("body", body)
.with("commit_id", sha)
.with("path", path)
.with("position", position)
.to(getApiRoute() + "/comments", GHPullRequestReviewComment.class).wrapUp(this);
}
/**
* Merge this pull request.
*
@@ -223,7 +266,21 @@ public class GHPullRequest extends GHIssue {
* 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");
merge(msg,null);
}
/**
* 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.
* @param sha
* SHA that pull request head must match to allow merge.
*/
public void merge(String msg, String sha) throws IOException {
new Requester(root).method("PUT").with("commit_message",msg).with("sha",sha).to(getApiRoute()+"/merge");
}
private void fetchIssue() throws IOException {

View File

@@ -24,106 +24,126 @@
package org.kohsuke.github;
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.net.URL;
import java.util.Arrays;
/**
* Commit detail inside a {@link GHPullRequest}.
*
* @author Luca Milanesio
* @see GHPullRequest#listCommits()
*/
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
"NP_UNWRITTEN_FIELD", "URF_UNREAD_FIELD"}, justification = "JSON API")
public class GHPullRequestCommitDetail {
private GHPullRequest owner;
/*package*/ void wrapUp(GHPullRequest owner) {
this.owner = owner;
}
/**
* @deprecated Use {@link GitUser}
*/
public static class Authorship extends 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 Tree getTree() {
return tree;
}
}
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;
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;
Commit commit;
String url;
String html_url;
public URL getUrl() {
return GitHub.parseURL(url);
}
public URL getHtml_url() {
return GitHub.parseURL(html_url);
}
String comments_url;
CommitPointer[] parents;
public String getSha() {
return sha;
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;
}
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 Arrays.copyOf(parents, parents.length);
}
}

View File

@@ -0,0 +1,86 @@
/*
* The MIT License
*
* Copyright (c) 2015, Julien Henry
*
* 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.net.URL;
/**
* File detail inside a {@link GHPullRequest}.
*
* @author Julien Henry
* @see GHPullRequest#listFiles()
*/
public class GHPullRequestFileDetail {
String sha;
String filename;
String status;
int additions;
int deletions;
int changes;
String blob_url;
String raw_url;
String contents_url;
String patch;
public String getSha() {
return sha;
}
public String getFilename() {
return filename;
}
public String getStatus() {
return status;
}
public int getAdditions() {
return additions;
}
public int getDeletions() {
return deletions;
}
public int getChanges() {
return changes;
}
public URL getBlobUrl() {
return GitHub.parseURL(blob_url);
}
public URL getRawUrl() {
return GitHub.parseURL(raw_url);
}
public URL getContentsUrl() {
return GitHub.parseURL(contents_url);
}
public String getPatch() {
return patch;
}
}

View File

@@ -0,0 +1,106 @@
/*
* 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.io.IOException;
import java.net.URL;
/**
* Review comment to the pull request
*
* @author Julien Henry
* @see GHPullRequest#listReviewComments()
* @see GHPullRequest#createReviewComment(String, String, String, int)
*/
public class GHPullRequestReviewComment extends GHObject {
GHPullRequest owner;
private String body;
private GHUser user;
private String path;
private int position;
private int originalPosition;
/*package*/ GHPullRequestReviewComment wrapUp(GHPullRequest owner) {
this.owner = owner;
return this;
}
/**
* Gets the pull request to which this review comment is associated.
*/
public GHPullRequest getParent() {
return owner;
}
/**
* The comment itself.
*/
public String getBody() {
return body;
}
/**
* Gets the user who posted this comment.
*/
public GHUser getUser() throws IOException {
return owner.root.getUser(user.getLogin());
}
public String getPath() {
return path;
}
public int getPosition() {
return position;
}
public int getOriginalPosition() {
return originalPosition;
}
@Override
public URL getHtmlUrl() {
return null;
}
protected String getApiRoute() {
return "/repos/"+owner.getRepository().getFullName()+"/pulls/comments/"+id;
}
/**
* Updates the comment.
*/
public void update(String body) throws IOException {
new Requester(owner.root).method("PATCH").with("body", body).to(getApiRoute(),this);
this.body = body;
}
/**
* Deletes this review comment.
*/
public void delete() throws IOException {
new Requester(owner.root).method("DELETE").to(getApiRoute());
}
}

View File

@@ -1,5 +1,6 @@
package org.kohsuke.github;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.Date;
/**
@@ -24,6 +25,8 @@ public class GHRateLimit {
/**
* Non-epoch date
*/
@SuppressFBWarnings(value = "UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR",
justification = "The value comes from JSON deserialization")
public Date getResetDate() {
return new Date(reset.getTime() * 1000);
}

View File

@@ -1,5 +1,6 @@
package org.kohsuke.github;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.IOException;
import java.net.URL;
@@ -77,7 +78,8 @@ public class GHRef {
return in;
}
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
"NP_UNWRITTEN_FIELD"}, justification = "JSON API")
public static class GHObject {
private String type, sha, url;

View File

@@ -3,6 +3,7 @@ package org.kohsuke.github;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
@@ -44,8 +45,14 @@ public class GHRelease extends GHObject {
return draft;
}
public String getHtmlUrl() {
return html_url;
public GHRelease setDraft(boolean draft) throws IOException {
edit("draft", draft);
this.draft = draft;
return this;
}
public URL getHtmlUrl() {
return GitHub.parseURL(html_url);
}
public String getName() {
@@ -69,7 +76,7 @@ public class GHRelease extends GHObject {
}
public Date getPublished_at() {
return published_at;
return new Date(published_at.getTime());
}
public GitHub getRoot() {
@@ -122,9 +129,14 @@ public class GHRelease extends GHObject {
String url = format("https://uploads.github.com%s/releases/%d/assets?name=%s",
owner.getApiTailUrl(""), getId(), file.getName());
return builder.contentType(contentType)
.with(new FileInputStream(file))
FileInputStream istream = new FileInputStream(file);
try {
return builder.contentType(contentType)
.with(istream)
.to(url, GHAsset.class).wrap(this);
} finally {
istream.close();
}
}
public List<GHAsset> getAssets() throws IOException {
@@ -143,6 +155,13 @@ public class GHRelease extends GHObject {
new Requester(root).method("DELETE").to(owner.getApiTailUrl("releases/"+id));
}
/**
* Edit this release.
*/
private void edit(String key, Object value) throws IOException {
new Requester(root)._with(key, value).method("PATCH").to(owner.getApiTailUrl("releases/"+id));
}
private String getApiTailUrl(String end) {
return owner.getApiTailUrl(format("releases/%s/%s",id,end));
}

View File

@@ -0,0 +1,23 @@
package org.kohsuke.github;
class GHRepoHook extends GHHook {
/**
* Repository that the hook belongs to.
*/
/*package*/ transient GHRepository repository;
/*package*/ GHRepoHook wrap(GHRepository owner) {
this.repository = owner;
return this;
}
@Override
GitHub getRoot() {
return repository.root;
}
@Override
String getApiRoute() {
return String.format("/repos/%s/%s/hooks/%d", repository.getOwnerName(), repository.getName(), id);
}
}

View File

@@ -25,6 +25,7 @@ package org.kohsuke.github;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import org.apache.commons.lang.StringUtils;
import javax.xml.bind.DatatypeConverter;
@@ -33,17 +34,21 @@ import java.io.IOException;
import java.io.InputStreamReader;
import java.io.InterruptedIOException;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.*;
import static java.util.Arrays.asList;
/**
* A repository on GitHub.
*
*
* @author Kohsuke Kawaguchi
*/
@SuppressWarnings({"UnusedDeclaration"})
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
"NP_UNWRITTEN_FIELD"}, justification = "JSON API")
public class GHRepository extends GHObject {
/*package almost final*/ GitHub root;
@@ -57,12 +62,14 @@ public class GHRepository extends GHObject {
private int watchers,forks,open_issues,size,network_count,subscribers_count;
private String pushed_at;
private Map<Integer,GHMilestone> milestones = new HashMap<Integer, GHMilestone>();
private String default_branch,language;
private Map<String,GHCommit> commits = new HashMap<String, GHCommit>();
private GHRepoPermission permissions;
private GHRepository source, parent;
public GHDeploymentBuilder createDeployment(String ref) {
return new GHDeploymentBuilder(this,ref);
}
@@ -159,6 +166,10 @@ public class GHRepository extends GHObject {
return ssh_url;
}
public URL getHtmlUrl() {
return GitHub.parseURL(html_url);
}
/**
* Short repository name without the owner. For example 'jenkins' in case of http://github.com/jenkinsci/jenkins
*/
@@ -211,7 +222,8 @@ public class GHRepository extends GHObject {
public List<GHIssue> getIssues(GHIssueState state, GHMilestone milestone) throws IOException {
return Arrays.asList(GHIssue.wrap(root.retrieve()
.to(getApiTailUrl(String.format("issues?state=%s&milestone=%s",
state.toString().toLowerCase(), milestone == null ? "none" : "" + milestone.getNumber())),
state.toString().toLowerCase(Locale.ENGLISH),
milestone == null ? "none" : "" + milestone.getNumber())),
GHIssue[].class
), this));
}
@@ -315,6 +327,10 @@ public class GHRepository extends GHObject {
return fork;
}
/**
* Returns the number of all forks of this repository.
* This not only counts direct forks, but also forks of forks, and so on.
*/
public int getForks() {
return forks;
}
@@ -353,11 +369,19 @@ public class GHRepository extends GHObject {
}
/**
* Returns the primary branch you'll configure in the "Admin > Options" config page.
* Returns the primary branch you'll configure in the "Admin &gt; Options" config page.
*
* @return
* This field is null until the user explicitly configures the master branch.
*/
public String getDefaultBranch() {
return default_branch;
}
/**
* @deprecated
* Renamed to {@link #getDefaultBranch()}
*/
public String getMasterBranch() {
return default_branch;
}
@@ -365,7 +389,8 @@ public class GHRepository extends GHObject {
public int getSize() {
return size;
}
/**
* Gets the collaborators on this repository.
* This set always appear to include the owner.
@@ -488,6 +513,10 @@ public class GHRepository extends GHObject {
edit("homepage",value);
}
public void setDefaultBranch(String value) throws IOException {
edit("default_branch", value);
}
/**
* Deletes this repository.
*/
@@ -499,6 +528,43 @@ public class GHRepository extends GHObject {
}
}
/**
* Sort orders for listing forks
*/
public static enum ForkSort { NEWEST, OLDEST, STARGAZERS }
/**
* Lists all the direct forks of this repository, sorted by
* github api default, currently {@link ForkSort#NEWEST ForkSort.NEWEST}.
*/
public PagedIterable<GHRepository> listForks() {
return listForks(null);
}
/**
* Lists all the direct forks of this repository, sorted by the given sort order.
* @param sort the sort order. If null, defaults to github api default,
* currently {@link ForkSort#NEWEST ForkSort.NEWEST}.
*/
public PagedIterable<GHRepository> listForks(final ForkSort sort) {
return new PagedIterable<GHRepository>() {
public PagedIterator<GHRepository> iterator() {
String sortParam = "";
if (sort != null) {
sortParam = "?sort=" + sort.toString().toLowerCase(Locale.ENGLISH);
}
return new PagedIterator<GHRepository>(root.retrieve().asIterator(getApiTailUrl("forks" + sortParam), GHRepository[].class)) {
@Override
protected void wrapUp(GHRepository[] page) {
for (GHRepository c : page) {
c.wrap(root);
}
}
};
}
};
}
/**
* Forks this repository as your repository.
*
@@ -591,15 +657,11 @@ public class GHRepository extends GHObject {
* Retrieves the currently configured hooks.
*/
public List<GHHook> getHooks() throws IOException {
List<GHHook> list = new ArrayList<GHHook>(Arrays.asList(
root.retrieve().to(getApiTailUrl("hooks"), GHHook[].class)));
for (GHHook h : list)
h.wrap(this);
return list;
return GHHooks.repoContext(this, owner).getHooks();
}
public GHHook getHook(int id) throws IOException {
return root.retrieve().to(getApiTailUrl("hooks/" + id), GHHook.class).wrap(this);
return GHHooks.repoContext(this, owner).getHook(id);
}
/**
@@ -642,48 +704,48 @@ public class GHRepository extends GHObject {
return GHRef.wrap(root.retrieve().to(String.format("/repos/%s/%s/git/refs/%s", owner.login, name, refType), GHRef[].class),root);
}
/**
* Retrive a ref of the given type for the current GitHub repository.
*
* @param refName
* eg: heads/branch
* @return refs matching the request type
* @throws IOException
* on failure communicating with GitHub, potentially due to an
* invalid ref type being requested
*/
public GHRef getRef(String refName) throws IOException {
return root.retrieve().to(String.format("/repos/%s/%s/git/refs/%s", owner.login, name, refName), GHRef.class).wrap(root);
}
* Retrive a ref of the given type for the current GitHub repository.
*
* @param refName
* eg: heads/branch
* @return refs matching the request type
* @throws IOException
* on failure communicating with GitHub, potentially due to an
* invalid ref type being requested
*/
public GHRef getRef(String refName) throws IOException {
return root.retrieve().to(String.format("/repos/%s/%s/git/refs/%s", owner.login, name, refName), GHRef.class).wrap(root);
}
/**
* Retrive a tree of the given type for the current GitHub repository.
*
* @param sha - sha number or branch name ex: "master"
* @return refs matching the request type
* @throws IOException
* on failure communicating with GitHub, potentially due to an
* invalid tree type being requested
*/
public GHTree getTree(String sha) throws IOException {
String url = String.format("/repos/%s/%s/git/trees/%s", owner.login, name, sha);
return root.retrieve().to(url, GHTree.class).wrap(root);
}
/**
* Retrieves the tree for the current GitHub repository, recursively as described in here:
* https://developer.github.com/v3/git/trees/#get-a-tree-recursively
*
* @param sha - sha number or branch name ex: "master"
* @param recursive use 1
* @throws IOException
* on failure communicating with GitHub, potentially due to an
* invalid tree type being requested
*/
public GHTree getTreeRecursive(String sha, int recursive) throws IOException {
String url = String.format("/repos/%s/%s/git/trees/%s?recursive=%d", owner.login, name, sha, recursive);
return root.retrieve().to(url, GHTree.class).wrap(root);
}
* Retrive a tree of the given type for the current GitHub repository.
*
* @param sha - sha number or branch name ex: "master"
* @return refs matching the request type
* @throws IOException
* on failure communicating with GitHub, potentially due to an
* invalid tree type being requested
*/
public GHTree getTree(String sha) throws IOException {
String url = String.format("/repos/%s/%s/git/trees/%s", owner.login, name, sha);
return root.retrieve().to(url, GHTree.class).wrap(root);
}
/**
/**
* Retrieves the tree for the current GitHub repository, recursively as described in here:
* https://developer.github.com/v3/git/trees/#get-a-tree-recursively
*
* @param sha - sha number or branch name ex: "master"
* @param recursive use 1
* @throws IOException
* on failure communicating with GitHub, potentially due to an
* invalid tree type being requested
*/
public GHTree getTreeRecursive(String sha, int recursive) throws IOException {
String url = String.format("/repos/%s/%s/git/trees/%s?recursive=%d", owner.login, name, sha, recursive);
return root.retrieve().to(url, GHTree.class).wrap(root);
}
/**
* Gets a commit object in this repository.
*/
public GHCommit getCommit(String sha1) throws IOException {
@@ -768,7 +830,7 @@ public class GHRepository extends GHObject {
* @param description
* Optional short description.
* @param context
* Optinal commit status context.
* Optinal commit status context.
*/
public GHCommitStatus createCommitStatus(String sha1, GHCommitState state, String targetUrl, String description, String context) throws IOException {
return new Requester(root)
@@ -778,12 +840,12 @@ public class GHRepository extends GHObject {
.with("context", context)
.to(String.format("/repos/%s/%s/statuses/%s",owner.login,this.name,sha1),GHCommitStatus.class).wrapUp(root);
}
/**
* @see {@link #createCommitStatus(String, GHCommitState,String,String,String) createCommitStatus}
* @see #createCommitStatus(String, GHCommitState,String,String,String)
*/
public GHCommitStatus createCommitStatus(String sha1, GHCommitState state, String targetUrl, String description) throws IOException {
return createCommitStatus(sha1, state, targetUrl, description,null);
return createCommitStatus(sha1, state, targetUrl, description,null);
}
/**
@@ -852,10 +914,10 @@ public class GHRepository extends GHObject {
}
/**
*
*
* 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. See https://api.github.com/hooks for possible names.
* @param config
@@ -864,21 +926,9 @@ public class GHRepository extends GHObject {
* Can be null. Types of events to hook into.
*/
public GHHook createHook(String name, Map<String,String> config, Collection<GHEvent> events, boolean active) throws IOException {
List<String> ea = null;
if (events!=null) {
ea = new ArrayList<String>();
for (GHEvent e : events)
ea.add(e.name().toLowerCase(Locale.ENGLISH));
}
return new Requester(root)
.with("name", name)
.with("active", active)
._with("config", config)
._with("events",ea)
.to(String.format("/repos/%s/%s/hooks",owner.login,this.name),GHHook.class).wrap(this);
return GHHooks.repoContext(this, owner).createHook(name, config, events, active);
}
public GHHook createWebHook(URL url, Collection<GHEvent> events) throws IOException {
return createHook("web",Collections.singletonMap("url",url.toExternalForm()),events,true);
}
@@ -903,10 +953,12 @@ public class GHRepository extends GHObject {
/**
* Returns a set that represents the post-commit hook URLs.
* The returned set is live, and changes made to them are reflected to GitHub.
*
* @deprecated
*
* @deprecated
* Use {@link #getHooks()} and {@link #createHook(String, Map, Collection, boolean)}
*/
@SuppressFBWarnings(value = "DMI_COLLECTION_OF_URLS",
justification = "It causes a performance degradation, but we have already exposed it to the API")
public Set<URL> getPostCommitHooks() {
return postCommitHooks;
}
@@ -914,6 +966,8 @@ public class GHRepository extends GHObject {
/**
* Live set view of the post-commit hook.
*/
@SuppressFBWarnings(value = "DMI_COLLECTION_OF_URLS",
justification = "It causes a performance degradation, but we have already exposed it to the API")
private final Set<URL> postCommitHooks = new AbstractSet<URL>() {
private List<URL> getPostCommitHooks() {
try {
@@ -989,10 +1043,10 @@ public class GHRepository extends GHObject {
*/
public Map<Integer, GHMilestone> getMilestones() throws IOException {
Map<Integer,GHMilestone> milestones = new TreeMap<Integer, GHMilestone>();
for (GHMilestone m : listMilestones(GHIssueState.OPEN)) {
milestones.put(m.getNumber(), m);
}
return milestones;
for (GHMilestone m : listMilestones(GHIssueState.OPEN)) {
milestones.put(m.getNumber(), m);
}
return milestones;
}
/**
@@ -1012,16 +1066,16 @@ public class GHRepository extends GHObject {
};
}
public GHMilestone getMilestone(int number) throws IOException {
GHMilestone m = milestones.get(number);
if (m == null) {
public GHMilestone getMilestone(int number) throws IOException {
GHMilestone m = milestones.get(number);
if (m == null) {
m = root.retrieve().to(getApiTailUrl("milestones/" + number), GHMilestone.class);
m.owner = this;
m.root = root;
milestones.put(m.getNumber(), m);
}
return m;
}
m.owner = this;
m.root = root;
milestones.put(m.getNumber(), m);
}
return m;
}
public GHContent getFileContent(String path) throws IOException {
return getFileContent(path, null);
@@ -1058,11 +1112,17 @@ public class GHRepository extends GHObject {
}
public GHContentUpdateResponse createContent(String content, String commitMessage, String path) throws IOException {
return createContent(content.getBytes(), commitMessage, path, null);
return createContent(content, commitMessage, path, null);
}
public GHContentUpdateResponse createContent(String content, String commitMessage, String path, String branch) throws IOException {
return createContent(content.getBytes(), commitMessage, path, branch);
final byte[] payload;
try {
payload = content.getBytes("UTF-8");
} catch (UnsupportedEncodingException ex) {
throw new IOException("UTF-8 encoding is not supported", ex);
}
return createContent(payload, commitMessage, path, branch);
}
public GHContentUpdateResponse createContent(byte[] contentBytes, String commitMessage, String path) throws IOException {
@@ -1088,24 +1148,56 @@ public class GHRepository extends GHObject {
return response;
}
public GHMilestone createMilestone(String title, String description) throws IOException {
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);
}
public GHDeployKey addDeployKey(String title,String key) throws IOException {
return new Requester(root)
}
public GHDeployKey addDeployKey(String title,String key) throws IOException {
return new Requester(root)
.with("title", title).with("key", key).method("POST").to(getApiTailUrl("keys"), GHDeployKey.class).wrap(this);
}
public List<GHDeployKey> getDeployKeys() throws IOException{
List<GHDeployKey> list = new ArrayList<GHDeployKey>(Arrays.asList(
root.retrieve().to(getApiTailUrl("keys"), GHDeployKey[].class)));
for (GHDeployKey h : list)
h.wrap(this);
return list;
}
}
public List<GHDeployKey> getDeployKeys() throws IOException{
List<GHDeployKey> list = new ArrayList<GHDeployKey>(Arrays.asList(
root.retrieve().to(getApiTailUrl("keys"), GHDeployKey[].class)));
for (GHDeployKey h : list)
h.wrap(this);
return list;
}
/**
* Forked repositories have a 'source' attribute that specifies the ultimate source of the forking chain.
*
* @return
* {@link GHRepository} that points to the root repository where this repository is forked
* (indirectly or directly) from. Otherwise null.
* @see #getParent()
*/
public GHRepository getSource() throws IOException {
if (source == null) return null;
if (source.root == null)
source = root.getRepository(source.getFullName());
return source;
}
/**
* Forked repositories have a 'parent' attribute that specifies the repository this repository
* is directly forked from. If we keep traversing {@link #getParent()} until it returns null, that
* is {@link #getSource()}.
*
* @return
* {@link GHRepository} that points to the repository where this repository is forked
* directly from. Otherwise null.
* @see #getSource()
*/
public GHRepository getParent() throws IOException {
if (parent == null) return null;
if (parent.root == null)
parent = root.getRepository(parent.getFullName());
return parent;
}
/**
* Subscribes to this repository to get notifications.
@@ -1124,7 +1216,7 @@ public class GHRepository extends GHObject {
*/
public GHSubscription getSubscription() throws IOException {
try {
return new Requester(root).to(getApiTailUrl("subscription"), GHSubscription.class).wrapUp(this);
return root.retrieve().to(getApiTailUrl("subscription"), GHSubscription.class).wrapUp(this);
} catch (FileNotFoundException e) {
return null;
}
@@ -1150,6 +1242,18 @@ public class GHRepository extends GHObject {
public int getContributions() {
return contributions;
}
@Override
public int hashCode() {
// We ignore contributions in the calculation
return super.hashCode();
}
@Override
public boolean equals(Object obj) {
// We ignore contributions in the calculation
return super.equals(obj);
}
}
/**

View File

@@ -1,10 +1,14 @@
package org.kohsuke.github;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
/**
* Represents a tag in {@link GHRepository}
*
* @see GHRepository#listTags()
*/
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
"NP_UNWRITTEN_FIELD"}, justification = "JSON API")
public class GHTag {
private GHRepository owner;
private GitHub root;

View File

@@ -47,10 +47,10 @@ public class GHTeam {
return id;
}
/**
* Retrieves the current members.
*/
public PagedIterable<GHUser> listMembers() throws IOException {
/**
* Retrieves the current members.
*/
public PagedIterable<GHUser> listMembers() throws IOException {
return new PagedIterable<GHUser>() {
public PagedIterator<GHUser> iterator() {
return new PagedIterator<GHUser>(org.root.retrieve().asIterator(api("/members"), GHUser[].class)) {
@@ -64,8 +64,8 @@ public class GHTeam {
}
public Set<GHUser> getMembers() throws IOException {
return Collections.unmodifiableSet(listMembers().asSet());
}
return Collections.unmodifiableSet(listMembers().asSet());
}
/**
* Checks if this team has the specified user as a member.

View File

@@ -1,7 +1,9 @@
package org.kohsuke.github;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.util.Date;
/**
@@ -11,6 +13,8 @@ import java.util.Date;
* @see GHNotificationStream
* @author Kohsuke Kawaguchi
*/
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
"NP_UNWRITTEN_FIELD"}, justification = "JSON API")
public class GHThread extends GHObject {
private GitHub root;
private GHRepository repository;
@@ -37,6 +41,14 @@ public class GHThread extends GHObject {
return GitHub.parseDate(last_read_at);
}
/**
* @deprecated This object has no HTML URL.
*/
@Override
public URL getHtmlUrl() {
return null;
}
public String getReason() {
return reason;
}
@@ -58,6 +70,45 @@ public class GHThread extends GHObject {
public String getType() {
return subject.type;
}
public String getLastCommentUrl() {
return subject.latest_comment_url;
}
/**
* If this thread is about an issue, return that issue.
*
* @return null if this thread is not about an issue.
*/
public GHIssue getBoundIssue() throws IOException {
if (!"Issue".equals(subject.type) && "PullRequest".equals(subject.type))
return null;
return repository.getIssue(
Integer.parseInt(subject.url.substring(subject.url.lastIndexOf('/') + 1)));
}
/**
* If this thread is about a pull request, return that pull request.
*
* @return null if this thread is not about a pull request.
*/
public GHPullRequest getBoundPullRequest() throws IOException {
if (!"PullRequest".equals(subject.type))
return null;
return repository.getPullRequest(
Integer.parseInt(subject.url.substring(subject.url.lastIndexOf('/') + 1)));
}
/**
* If this thread is about a commit, return that commit.
*
* @return null if this thread is not about a commit.
*/
public GHCommit getBoundCommit() throws IOException {
if (!"Commit".equals(subject.type))
return null;
return repository.getCommit(subject.url.substring(subject.url.lastIndexOf('/') + 1));
}
/*package*/ GHThread wrap(GitHub root) {
this.root = root;

View File

@@ -13,46 +13,46 @@ import java.util.List;
* @see GHRepository#getTree(String)
*/
public class GHTree {
/* package almost final */GitHub root;
/* package almost final */GitHub root;
private boolean truncated;
private String sha, url;
private GHTreeEntry[] tree;
private boolean truncated;
private String sha, url;
private GHTreeEntry[] tree;
/**
* The SHA for this trees
*/
public String getSha() {
return sha;
}
/**
* The SHA for this trees
*/
public String getSha() {
return sha;
}
/**
* Return an array of entries of the trees
* @return
*/
public List<GHTreeEntry> getTree() {
return Collections.unmodifiableList(Arrays.asList(tree));
}
/**
* Return an array of entries of the trees
* @return
*/
public List<GHTreeEntry> getTree() {
return Collections.unmodifiableList(Arrays.asList(tree));
}
/**
* Returns true if the number of items in the tree array exceeded the GitHub maximum limit.
* @return true true if the number of items in the tree array exceeded the GitHub maximum limit otherwise false.
*/
public boolean isTruncated() {
return truncated;
}
/**
* Returns true if the number of items in the tree array exceeded the GitHub maximum limit.
* @return true true if the number of items in the tree array exceeded the GitHub maximum limit otherwise false.
*/
public boolean isTruncated() {
return truncated;
}
/**
* The API URL of this tag, such as
* "url": "https://api.github.com/repos/octocat/Hello-World/trees/fc6274d15fa3ae2ab983129fb037999f264ba9a7",
*/
public URL getUrl() {
return GitHub.parseURL(url);
}
/**
* The API URL of this tag, such as
* "url": "https://api.github.com/repos/octocat/Hello-World/trees/fc6274d15fa3ae2ab983129fb037999f264ba9a7",
*/
public URL getUrl() {
return GitHub.parseURL(url);
}
/* package */GHTree wrap(GitHub root) {
this.root = root;
return this;
}
/* package */GHTree wrap(GitHub root) {
this.root = root;
return this;
}
}

View File

@@ -45,6 +45,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import org.apache.commons.codec.binary.Base64;
@@ -52,6 +53,7 @@ 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;
import java.nio.charset.Charset;
/**
* Root of the GitHub API.
@@ -60,7 +62,7 @@ import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
* <p>
* This library aims to be safe for use by multiple threads concurrently, although
* the library itself makes no attempt to control/serialize potentially conflicting
* operations to GitHub, such as updating & deleting a repository at the same time.
* operations to GitHub, such as updating &amp; deleting a repository at the same time.
*
* @author Kohsuke Kawaguchi
*/
@@ -127,16 +129,23 @@ public class GitHub {
} else {
if (password!=null) {
String authorization = (login + ':' + password);
encodedAuthorization = "Basic "+new String(Base64.encodeBase64(authorization.getBytes()));
final Charset charset;
try {
charset = Charset.forName("UTF-8");
} catch (Exception ex) {
throw new IOException("UTF-8 encoding is not supported", ex);
}
encodedAuthorization = "Basic "+new String(Base64.encodeBase64(authorization.getBytes(charset)), charset);
} else {// anonymous access
encodedAuthorization = null;
}
}
this.rateLimitHandler = rateLimitHandler;
if (login==null && encodedAuthorization!=null)
login = getMyself().getLogin();
this.login = login;
this.rateLimitHandler = rateLimitHandler;
}
/**
@@ -247,16 +256,17 @@ public class GitHub {
// see issue #78
GHRateLimit r = new GHRateLimit();
r.limit = r.remaining = 1000000;
r.reset = new Date(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(1));
return r;
}
}
/**
* Gets the {@link GHUser} that represents yourself.
*/
* Gets the {@link GHUser} that represents yourself.
*/
@WithBridgeMethods(GHUser.class)
public GHMyself getMyself() throws IOException {
requireCredential();
public GHMyself getMyself() throws IOException {
requireCredential();
GHMyself u = retrieve().to("/user", GHMyself.class);
@@ -264,20 +274,20 @@ public class GitHub {
users.put(u.getLogin(), u);
return u;
}
}
/**
* Obtains the object that represents the named user.
*/
public GHUser getUser(String login) throws IOException {
GHUser u = users.get(login);
if (u == null) {
/**
* Obtains the object that represents the named user.
*/
public GHUser getUser(String login) throws IOException {
GHUser u = users.get(login);
if (u == null) {
u = retrieve().to("/users/" + login, GHUser.class);
u.root = this;
users.put(u.getLogin(), u);
}
return u;
}
}
return u;
}
/**
@@ -415,14 +425,14 @@ public class GitHub {
*
* @see <a href="http://developer.github.com/v3/oauth/#create-a-new-authorization">Documentation</a>
*/
public GHAuthorization createToken(Collection<String> scope, String note, String noteUrl) throws IOException{
Requester requester = new Requester(this)
.with("scopes", scope)
.with("note", note)
.with("note_url", noteUrl);
public GHAuthorization createToken(Collection<String> scope, String note, String noteUrl) throws IOException{
Requester requester = new Requester(this)
.with("scopes", scope)
.with("note", note)
.with("note_url", noteUrl);
return requester.method("POST").to("/authorizations", GHAuthorization.class).wrap(this);
}
return requester.method("POST").to("/authorizations", GHAuthorization.class).wrap(this);
}
/**
* Ensures that the credential is valid.

View File

@@ -45,18 +45,18 @@ public class GitHubBuilder {
* @throws IOException If there are no credentials defined in the ~/.github properties file or the process environment.
*/
public static GitHubBuilder fromCredentials() throws IOException {
Exception cause = null;
GitHubBuilder builder;
Exception cause = null;
GitHubBuilder builder;
try {
builder = fromPropertyFile();
try {
builder = fromPropertyFile();
if (builder.user != null)
return builder;
} catch (FileNotFoundException e) {
if (builder.user != null)
return builder;
} catch (FileNotFoundException e) {
// fall through
cause = e;
}
}
builder = fromEnvironment();
@@ -77,8 +77,8 @@ public class GitHubBuilder {
private static void loadIfSet(String envName, Properties p, String propName) {
String v = System.getenv(envName);
if (v != null)
p.put(propName, v);
if (v != null)
p.put(propName, v);
}
/**
@@ -87,12 +87,12 @@ public class GitHubBuilder {
* different clients of this library will all recognize one consistent set of coordinates.
*/
public static GitHubBuilder fromEnvironment(String loginVariableName, String passwordVariableName, String oauthVariableName, String endpointVariableName) throws IOException {
Properties env = new Properties();
loadIfSet(loginVariableName,env,"login");
Properties env = new Properties();
loadIfSet(loginVariableName,env,"login");
loadIfSet(passwordVariableName,env,"password");
loadIfSet(oauthVariableName,env,"oauth");
loadIfSet(endpointVariableName,env,"endpoint");
return fromProperties(env);
return fromProperties(env);
}
/**
@@ -116,7 +116,7 @@ public class GitHubBuilder {
* login, password, oauth
*/
public static GitHubBuilder fromEnvironment() throws IOException {
Properties props = new Properties();
Properties props = new Properties();
for (Entry<String, String> e : System.getenv().entrySet()) {
String name = e.getKey().toLowerCase(Locale.ENGLISH);
if (name.startsWith("github_")) name=name.substring(7);

View File

@@ -1,5 +1,6 @@
package org.kohsuke.github;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.Date;
/**
@@ -11,6 +12,8 @@ import java.util.Date;
*
* @author Kohsuke Kawaguchi
*/
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
"NP_UNWRITTEN_FIELD"}, justification = "JSON API")
public class GitUser {
private String name, email, date;

View File

@@ -1,5 +1,6 @@
package org.kohsuke.github;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.Iterator;
/**
@@ -7,6 +8,8 @@ import java.util.Iterator;
*
* @author Kohsuke Kawaguchi
*/
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR"}, justification = "Constructed by JSON API")
public abstract class PagedSearchIterable<T> extends PagedIterable<T> {
private final GitHub root;

View File

@@ -53,6 +53,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
import static java.util.Arrays.asList;
import static org.kohsuke.github.GitHub.*;
/**
@@ -61,6 +62,8 @@ import static org.kohsuke.github.GitHub.*;
* @author Kohsuke Kawaguchi
*/
class Requester {
private static final List<String> METHODS_WITHOUT_BODY = asList("GET", "DELETE");
private final GitHub root;
private final List<Entry> args = new ArrayList<Entry>();
private final Map<String,String> headers = new LinkedHashMap<String, String>();
@@ -116,7 +119,7 @@ class Requester {
public Requester with(String key, Integer value) {
if (value!=null)
_with(key, value.intValue());
_with(key, value);
return this;
}
@@ -208,7 +211,7 @@ class Requester {
private <T> T _to(String tailApiUrl, Class<T> type, T instance) throws IOException {
while (true) {// loop while API rate limit is hit
if (method.equals("GET") && !args.isEmpty()) {
if (METHODS_WITHOUT_BODY.contains(method) && !args.isEmpty()) {
StringBuilder qs=new StringBuilder();
for (Entry arg : args) {
qs.append(qs.length()==0 ? '?' : '&');
@@ -287,7 +290,7 @@ class Requester {
* Set up the request parameters or POST payload.
*/
private void buildRequest() throws IOException {
if (!method.equals("GET")) {
if (isMethodWithBody()) {
uc.setDoOutput(true);
uc.setRequestProperty("Content-type", contentType);
@@ -311,28 +314,35 @@ class Requester {
}
}
private boolean isMethodWithBody() {
return !METHODS_WITHOUT_BODY.contains(method);
}
/**
* Loads pagenated resources.
*
* Every iterator call reports a new batch.
*/
/*package*/ <T> Iterator<T> asIterator(String _tailApiUrl, final Class<T> type) {
/*package*/ <T> Iterator<T> asIterator(final String _tailApiUrl, final Class<T> type) {
method("GET");
final StringBuilder strBuilder = new StringBuilder(_tailApiUrl);
if (!args.isEmpty()) {
boolean first=true;
try {
for (Entry a : args) {
_tailApiUrl += first ? '?' : '&';
strBuilder.append(first ? '?' : '&');
first = false;
_tailApiUrl += URLEncoder.encode(a.key,"UTF-8")+'='+URLEncoder.encode(a.value.toString(),"UTF-8");
strBuilder.append(URLEncoder.encode(a.key, "UTF-8"));
strBuilder.append('=');
strBuilder.append(URLEncoder.encode(a.value.toString(), "UTF-8"));
}
} catch (UnsupportedEncodingException e) {
throw new AssertionError(e); // UTF-8 is mandatory
}
}
final String tailApiUrl = _tailApiUrl;
final String tailApiUrl = strBuilder.toString();
return new Iterator<T>() {
/**
@@ -479,6 +489,9 @@ class Requester {
* Handle API error by either throwing it or by returning normally to retry.
*/
/*package*/ void handleApiError(IOException e) throws IOException {
if (uc.getResponseCode() == 401) // Unauthorized == bad creds
throw e;
if ("0".equals(uc.getHeaderField("X-RateLimit-Remaining"))) {
root.rateLimitHandler.onError(e,uc);
}
@@ -497,11 +510,4 @@ class Requester {
IOUtils.closeQuietly(es);
}
}
private Set<String> toSet(String s) {
Set<String> r = new HashSet<String>();
for (String t : s.split(","))
r.add(t.trim());
return r;
}
}

View File

@@ -1,12 +1,18 @@
package org.kohsuke.github;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
/**
* Represents the result of a search
*
* @author Kohsuke Kawaguchi
*/
abstract class SearchResult<T> {
@SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization")
int total_count;
@SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization")
boolean incomplete_results;
/**

View File

@@ -19,9 +19,9 @@ public abstract class AbstractGitHubApiTestBase extends Assert {
if (f.exists()) {
// use the non-standard credential preferentially, so that developers of this library do not have
// to clutter their event stream.
gitHub = GitHubBuilder.fromPropertyFile(f.getPath()).build();
gitHub = GitHubBuilder.fromPropertyFile(f.getPath()).withRateLimitHandler(RateLimitHandler.FAIL).build();
} else {
gitHub = GitHub.connect();
gitHub = GitHubBuilder.fromCredentials().withRateLimitHandler(RateLimitHandler.FAIL).build();
}
}

View File

@@ -351,7 +351,7 @@ public class AppTest extends AbstractGitHubApiTestBase {
sha1.add(c.getSHA1());
}
assertEquals("1cccddb22e305397151b2b7b87b4b47d74ca337b",sha1.get(0));
assertEquals(29,sha1.size());
assertEquals(29, sha1.size());
}
@Test
@@ -598,10 +598,10 @@ public class AppTest extends AbstractGitHubApiTestBase {
}
@Test
public void testRef() throws IOException {
GHRef masterRef = gitHub.getRepository("jenkinsci/jenkins").getRef("heads/master");
assertEquals("https://api.github.com/repos/jenkinsci/jenkins/git/refs/heads/master", masterRef.getUrl().toString());
}
public void testRef() throws IOException {
GHRef masterRef = gitHub.getRepository("jenkinsci/jenkins").getRef("heads/master");
assertEquals("https://api.github.com/repos/jenkinsci/jenkins/git/refs/heads/master", masterRef.getUrl().toString());
}
@Test
public void directoryListing() throws IOException {
@@ -618,8 +618,8 @@ public class AppTest extends AbstractGitHubApiTestBase {
@Test
public void testAddDeployKey() throws IOException {
GHRepository myRepository = Iterables.get(gitHub.getMyself().getRepositories().values(),0);
final GHDeployKey newDeployKey = myRepository.addDeployKey("test", "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDUt0RAycC5cS42JKh6SecfFZBR1RrF+2hYMctz4mk74/arBE+wFb7fnSHGzdGKX2h5CFOWODifRCJVhB7hlVxodxe+QkQQYAEL/x1WVCJnGgTGQGOrhOMj95V3UE5pQKhsKD608C+u5tSofcWXLToP1/wZ7U4/AHjqYi08OLsWToHCax55TZkvdt2jo0hbIoYU+XI9Q8Uv4ONDN1oabiOdgeKi8+crvHAuvNleiBhWVBzFh8KdfzaH5uNdw7ihhFjEd1vzqACsjCINCjdMfzl6jD9ExuWuE92nZJnucls2cEoNC6k2aPmrZDg9hA32FXVpyseY+bDUWFU6LO2LG6PB kohsuke@atlas");
GHRepository myRepository = getTestRepository();
final GHDeployKey newDeployKey = myRepository.addDeployKey("test", "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDUt0RAycC5cS42JKh6SecfFZBR1RrF+2hYMctz4mk74/arBE+wFb7fnSHGzdGKX2h5CFOWODifRCJVhB7hlVxodxe+QkQQYAEL/x1WVCJnGgTGQGOrhOMj95V3UE5pQKhsKD608C+u5tSofcWXLToP1/wZ7U4/AHjqYi08OLsWToHCax55TZkvdt2jo0hbIoYU+XI9Q8Uv4ONDN1oabiOdgeKi8+crvHAuvNleiBhWVBzFh8KdfzaH5uNdw7ihhFjEd1vzqACsjCINCjdMfzl6jD9ExuWuE92nZJnucls2cEoNC6k2aPmrZDg9hA32FXVpyseY+bDUWFU6LO2LG6PB kohsuke@atlas");
try {
assertNotNull(newDeployKey.getId());
@@ -636,11 +636,11 @@ public class AppTest extends AbstractGitHubApiTestBase {
@Test
public void testCommitStatusContext() throws IOException {
GHRepository myRepository = Iterables.get(gitHub.getMyself().getRepositories().values(), 0);
GHRef masterRef = myRepository.getRef("heads/master");
GHCommitStatus commitStatus = myRepository.createCommitStatus(masterRef.getObject().getSha(), GHCommitState.SUCCESS, "http://www.example.com", "test", "test/context");
assertEquals("test/context", commitStatus.getContext());
GHRepository myRepository = getTestRepository();
GHRef masterRef = myRepository.getRef("heads/master");
GHCommitStatus commitStatus = myRepository.createCommitStatus(masterRef.getObject().getSha(), GHCommitState.SUCCESS, "http://www.example.com", "test", "test/context");
assertEquals("test/context", commitStatus.getContext());
}
@Test
@@ -671,28 +671,28 @@ public class AppTest extends AbstractGitHubApiTestBase {
@Test
public void testTrees() throws IOException {
GHTree masterTree = gitHub.getRepository("kohsuke/github-api").getTree("master");
boolean foundReadme = false;
for(GHTreeEntry e : masterTree.getTree()){
if("readme".equalsIgnoreCase(e.getPath().replaceAll(".md", ""))){
foundReadme = true;
break;
}
}
assertTrue(foundReadme);
GHTree masterTree = gitHub.getRepository("kohsuke/github-api").getTree("master");
boolean foundReadme = false;
for(GHTreeEntry e : masterTree.getTree()){
if("readme".equalsIgnoreCase(e.getPath().replaceAll("\\.md", ""))){
foundReadme = true;
break;
}
}
assertTrue(foundReadme);
}
@Test
public void testTreesRecursive() throws IOException {
GHTree masterTree = gitHub.getRepository("kohsuke/github-api").getTreeRecursive("master", 1);
boolean foundThisFile = false;
for(GHTreeEntry e : masterTree.getTree()){
if(e.getPath().endsWith(AppTest.class.getSimpleName() + ".java")){
foundThisFile = true;
break;
}
}
assertTrue(foundThisFile);
GHTree masterTree = gitHub.getRepository("kohsuke/github-api").getTreeRecursive("master", 1);
boolean foundThisFile = false;
for(GHTreeEntry e : masterTree.getTree()){
if(e.getPath().endsWith(AppTest.class.getSimpleName() + ".java")){
foundThisFile = true;
break;
}
}
assertTrue(foundThisFile);
}
@Test

View File

@@ -1,50 +1,56 @@
package org.kohsuke.github;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import junit.framework.TestCase;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
/**
* Unit test for {@link GitHub}.
*/
public class GitHubTest extends TestCase {
public class GitHubTest {
@Test
public void testGitHubServerWithHttp() throws Exception {
GitHub hub = GitHub.connectToEnterprise("http://enterprise.kohsuke.org/api/v3", "bogus","bogus");
assertEquals("http://enterprise.kohsuke.org/api/v3/test", hub.getApiURL("/test").toString());
}
@Test
public void testGitHubServerWithHttps() throws Exception {
GitHub hub = GitHub.connectToEnterprise("https://enterprise.kohsuke.org/api/v3", "bogus","bogus");
assertEquals("https://enterprise.kohsuke.org/api/v3/test", hub.getApiURL("/test").toString());
}
@Test
public void testGitHubServerWithoutServer() throws Exception {
GitHub hub = GitHub.connectUsingPassword("kohsuke", "bogus");
assertEquals("https://api.github.com/test", hub.getApiURL("/test").toString());
}
@Test
public void testGitHubBuilderFromEnvironment() throws IOException {
Map<String, String>props = new HashMap<String, String>();
props.put("login", "bogus");
props.put("oauth", "bogus");
props.put("password", "bogus");
setupEnvironment(props);
GitHubBuilder builder = GitHubBuilder.fromEnvironment();
assertEquals("bogus", builder.user);
assertEquals("bogus", builder.oauthToken);
assertEquals("bogus", builder.password);
Map<String, String>props = new HashMap<String, String>();
props.put("login", "bogus");
props.put("oauth", "bogus");
props.put("password", "bogus");
setupEnvironment(props);
GitHubBuilder builder = GitHubBuilder.fromEnvironment();
assertEquals("bogus", builder.user);
assertEquals("bogus", builder.oauthToken);
assertEquals("bogus", builder.password);
}
/*
@@ -55,59 +61,62 @@ public class GitHubTest extends TestCase {
* Its used to wire in values for the github credentials to test that the GitHubBuilder works properly to resolve them.
*/
private void setupEnvironment(Map<String, String> newenv) {
try
{
Class<?> processEnvironmentClass = Class.forName("java.lang.ProcessEnvironment");
Field theEnvironmentField = processEnvironmentClass.getDeclaredField("theEnvironment");
theEnvironmentField.setAccessible(true);
Map<String, String> env = (Map<String, String>) theEnvironmentField.get(null);
env.putAll(newenv);
Field theCaseInsensitiveEnvironmentField = processEnvironmentClass.getDeclaredField("theCaseInsensitiveEnvironment");
theCaseInsensitiveEnvironmentField.setAccessible(true);
Map<String, String> cienv = (Map<String, String>) theCaseInsensitiveEnvironmentField.get(null);
cienv.putAll(newenv);
}
catch (NoSuchFieldException e)
{
try {
Class[] classes = Collections.class.getDeclaredClasses();
Map<String, String> env = System.getenv();
for(Class cl : classes) {
if("java.util.Collections$UnmodifiableMap".equals(cl.getName())) {
Field field = cl.getDeclaredField("m");
field.setAccessible(true);
Object obj = field.get(env);
Map<String, String> map = (Map<String, String>) obj;
map.clear();
map.putAll(newenv);
}
}
} catch (Exception e2) {
e2.printStackTrace();
}
} catch (Exception e1) {
e1.printStackTrace();
}
}
public void testGitHubBuilderFromCustomEnvironment() throws IOException {
Map<String, String>props = new HashMap<String, String>();
props.put("customLogin", "bogusLogin");
props.put("customOauth", "bogusOauth");
props.put("customPassword", "bogusPassword");
props.put("customEndpoint", "bogusEndpoint");
setupEnvironment(props);
GitHubBuilder builder = GitHubBuilder.fromEnvironment("customLogin", "customPassword", "customOauth", "customEndpoint");
assertEquals("bogusLogin", builder.user);
assertEquals("bogusOauth", builder.oauthToken);
assertEquals("bogusPassword", builder.password);
assertEquals("bogusEndpoint", builder.endpoint);
try {
Class<?> processEnvironmentClass = Class.forName("java.lang.ProcessEnvironment");
Field theEnvironmentField = processEnvironmentClass.getDeclaredField("theEnvironment");
theEnvironmentField.setAccessible(true);
Map<String, String> env = (Map<String, String>) theEnvironmentField.get(null);
env.putAll(newenv);
Field theCaseInsensitiveEnvironmentField = processEnvironmentClass.getDeclaredField("theCaseInsensitiveEnvironment");
theCaseInsensitiveEnvironmentField.setAccessible(true);
Map<String, String> cienv = (Map<String, String>) theCaseInsensitiveEnvironmentField.get(null);
cienv.putAll(newenv);
} catch (NoSuchFieldException e) {
try {
Class[] classes = Collections.class.getDeclaredClasses();
Map<String, String> env = System.getenv();
for (Class cl : classes) {
if ("java.util.Collections$UnmodifiableMap".equals(cl.getName())) {
Field field = cl.getDeclaredField("m");
field.setAccessible(true);
Object obj = field.get(env);
Map<String, String> map = (Map<String, String>) obj;
map.clear();
map.putAll(newenv);
}
}
} catch (Exception e2) {
e2.printStackTrace();
}
} catch (Exception e1) {
e1.printStackTrace();
}
}
@Test
public void testGitHubBuilderFromCustomEnvironment() throws IOException {
Map<String, String> props = new HashMap<String, String>();
props.put("customLogin", "bogusLogin");
props.put("customOauth", "bogusOauth");
props.put("customPassword", "bogusPassword");
props.put("customEndpoint", "bogusEndpoint");
setupEnvironment(props);
GitHubBuilder builder = GitHubBuilder.fromEnvironment("customLogin", "customPassword", "customOauth", "customEndpoint");
assertEquals("bogusLogin", builder.user);
assertEquals("bogusOauth", builder.oauthToken);
assertEquals("bogusPassword", builder.password);
assertEquals("bogusEndpoint", builder.endpoint);
}
@Test
public void testGitHubEnterpriseDoesNotHaveRateLimit() throws IOException {
GitHub github = spy(new GitHubBuilder().build());
when(github.retrieve()).thenThrow(FileNotFoundException.class);
GHRateLimit rateLimit = github.getRateLimit();
assertThat(rateLimit.getResetDate(), notNullValue());
}
}

View File

@@ -5,6 +5,7 @@ import org.junit.Test;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
/**
* @author Kohsuke Kawaguchi
@@ -18,7 +19,38 @@ public class PullRequestTest extends AbstractGitHubApiTestBase {
assertEquals(name, p.getTitle());
}
@Test // Requires push access to the test repo to pass
@Test
public void createPullRequestComment() throws Exception {
String name = rnd.next();
GHPullRequest p = getRepository().createPullRequest(name, "stable", "master", "## test");
p.comment("Some comment");
}
@Test
public void testPullRequestReviewComments() throws Exception {
String name = rnd.next();
GHPullRequest p = getRepository().createPullRequest(name, "stable", "master", "## test");
System.out.println(p.getUrl());
assertTrue(p.listReviewComments().asList().isEmpty());
p.createReviewComment("Sample review comment", p.getHead().getSha(), "cli/pom.xml", 5);
List<GHPullRequestReviewComment> comments = p.listReviewComments().asList();
assertEquals(1, comments.size());
GHPullRequestReviewComment comment = comments.get(0);
assertEquals("Sample review comment", comment.getBody());
comment.update("Updated review comment");
comments = p.listReviewComments().asList();
assertEquals(1, comments.size());
comment = comments.get(0);
assertEquals("Updated review comment", comment.getBody());
comment.delete();
comments = p.listReviewComments().asList();
assertTrue(comments.isEmpty());
}
@Test
// Requires push access to the test repo to pass
public void setLabels() throws Exception {
GHPullRequest p = getRepository().createPullRequest(rnd.next(), "stable", "master", "## test");
String label = rnd.next();
@@ -29,7 +61,8 @@ public class PullRequestTest extends AbstractGitHubApiTestBase {
assertEquals(label, labels.iterator().next().getName());
}
@Test // Requires push access to the test repo to pass
@Test
// Requires push access to the test repo to pass
public void setAssignee() throws Exception {
GHPullRequest p = getRepository().createPullRequest(rnd.next(), "stable", "master", "## test");
GHMyself user = gitHub.getMyself();
@@ -49,7 +82,7 @@ public class PullRequestTest extends AbstractGitHubApiTestBase {
PagedIterable<GHPullRequest> ghPullRequests = getRepository().listPullRequests(GHIssueState.OPEN);
for (GHPullRequest pr : ghPullRequests) {
assertNotNull(pr.getUser().root);
assertFalse(pr.getMergeable());
pr.getMergeable();
assertNotNull(pr.getUser().root);
}
}