diff --git a/pom.xml b/pom.xml index f756423936..30cb8acd1b 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.10 + 1.11 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java diff --git a/src/main/java/org/kohsuke/github/ApiVersion.java b/src/main/java/org/kohsuke/github/ApiVersion.java new file mode 100644 index 0000000000..52ecedb14e --- /dev/null +++ b/src/main/java/org/kohsuke/github/ApiVersion.java @@ -0,0 +1,17 @@ +package org.kohsuke.github; + +/** + * Different API versions. + * + * @author Kohsuke Kawaguchi + */ +enum ApiVersion { + V2("https://github.com/api/v2/json"), + V3("https://api.github.com"); + + final String url; + + ApiVersion(String url) { + this.url = url; + } +} diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index abfbfbbb14..925214090c 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -32,6 +32,7 @@ import com.gargoylesoftware.htmlunit.html.HtmlPage; import java.io.IOException; +import java.lang.annotation.RetentionPolicy; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.net.URL; @@ -47,6 +48,7 @@ import java.util.Set; import static java.util.Arrays.*; +import static org.kohsuke.github.ApiVersion.V3; /** * A repository on GitHub. @@ -158,7 +160,7 @@ public Set getCollaboratorNames() throws IOException { * If this repository belongs to an organization, return a set of teams. */ public Set getTeams() throws IOException { - return Collections.unmodifiableSet(root.retrieve("/repos/show/"+owner+"/"+name+"/teams",JsonTeams.class).toSet( + return Collections.unmodifiableSet(root.retrieveWithAuth("/repos/show/"+owner+"/"+name+"/teams",JsonTeams.class).toSet( root.getOrganization(owner))); } @@ -233,22 +235,8 @@ public GHRepository fork() throws IOException { * Newly forked repository that belong to you. */ public GHRepository forkTo(GHOrganization org) throws IOException { - WebClient wc = root.createWebClient(); - HtmlPage pg = (HtmlPage)wc.getPage(getUrl()); - for (HtmlForm f : pg.getForms()) { - if (!f.getActionAttribute().endsWith("/fork")) continue; - try { - if (org.getLogin().equals(f.getInputByName("organization").getValueAttribute())) { - // found it - f.submit((HtmlButton)f.getElementsByTagName("button").get(0)); - return org.getRepository(name); - } - } catch (ElementNotFoundException e) { - // continue - } - } - - throw new IllegalArgumentException("Either you don't have the privilege to fork into "+org.getLogin()+" or there's a bug in HTML scraping"); + new Poster(root, V3).withCredential().to(String.format("/repos/%s/%s/forks?org=%s",owner,name,org.getLogin())); + return org.getRepository(name); } /** diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index c4f5b893c4..8eb543b949 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -60,7 +60,8 @@ public class GitHub { /*package*/ final String login; /*package*/ final String encodedAuthorization; - final String password; + /*package*/ final String password; + /*package*/ final String apiToken; private final Map users = new HashMap(); private final Map orgs = new HashMap(); @@ -68,11 +69,12 @@ public class GitHub { private GitHub(String login, String apiToken, String password) { this.login = login; + this.apiToken = apiToken; this.password = password; BASE64Encoder enc = new sun.misc.BASE64Encoder(); if (apiToken!=null || password!=null) { - String userpassword = apiToken!=null ? (login + "/token" + ":" + apiToken) : (login + ':'+password); + String userpassword = password==null ? (login + "/token" + ":" + apiToken) : (login + ':'+password); encodedAuthorization = enc.encode(userpassword.getBytes()); } else encodedAuthorization = null; @@ -84,11 +86,11 @@ private GitHub (String oauthAccessToken) throws IOException { this.encodedAuthorization = null; this.oauthAccessToken = oauthAccessToken; + this.apiToken = oauthAccessToken; this.login = getMyself().getLogin(); - - } + /** * Obtains the credential from "~/.github" */ @@ -129,16 +131,13 @@ public static GitHub connectAnonymously() { throw new IllegalStateException("This operation requires a credential but none is given to the GitHub constructor"); } - /*package*/ URL getApiURL(String tailApiUrl) throws IOException { - + /*package*/ URL getApiURL(ApiVersion v, String tailApiUrl) throws IOException { if (oauthAccessToken != null) { // append the access token - tailApiUrl = tailApiUrl + "?access_token=" + oauthAccessToken; } - return new URL("https://github.com/api/v2/json"+tailApiUrl); - + return new URL(v.url+tailApiUrl); } /*package*/ T retrieve(String tailApiUrl, Class type) throws IOException { @@ -157,7 +156,7 @@ private T _retrieve(String tailApiUrl, Class type, String method, boolean while (true) {// loop while API rate limit is hit - HttpURLConnection uc = (HttpURLConnection) getApiURL(tailApiUrl).openConnection(); + HttpURLConnection uc = (HttpURLConnection) getApiURL(ApiVersion.V2,tailApiUrl).openConnection(); if (withAuth && this.oauthAccessToken == null) uc.setRequestProperty("Authorization", "Basic " + encodedAuthorization); diff --git a/src/main/java/org/kohsuke/github/Poster.java b/src/main/java/org/kohsuke/github/Poster.java index 700eb5f532..29097a282c 100644 --- a/src/main/java/org/kohsuke/github/Poster.java +++ b/src/main/java/org/kohsuke/github/Poster.java @@ -46,8 +46,15 @@ class Poster { private final List args = new ArrayList(); private boolean authenticate; - Poster(GitHub root) { + private final ApiVersion v; + + Poster(GitHub root, ApiVersion v) { this.root = root; + this.v = v; + } + + Poster(GitHub root) { + this(root,ApiVersion.V2); } public Poster withCredential() { @@ -89,12 +96,19 @@ public T to(String tailApiUrl, Class type) throws IOException { public T to(String tailApiUrl, Class type, String method) throws IOException { while (true) {// loop while API rate limit is hit - HttpURLConnection uc = (HttpURLConnection) root.getApiURL(tailApiUrl).openConnection(); + HttpURLConnection uc = (HttpURLConnection) root.getApiURL(v,tailApiUrl).openConnection(); uc.setDoOutput(true); uc.setRequestProperty("Content-type","application/x-www-form-urlencoded"); - if (authenticate) - uc.setRequestProperty("Authorization", "Basic " + root.encodedAuthorization); + if (authenticate) { + if (v==ApiVersion.V3) { + if (root.password==null) + throw new IllegalArgumentException("V3 API doesn't support API token"); + uc.setRequestProperty("Authorization", "Basic " + root.encodedAuthorization); + } else { + uc.setRequestProperty("Authorization", "Basic " + root.encodedAuthorization); + } + } uc.setRequestMethod(method); diff --git a/src/test/java/org/kohsuke/AppTest.java b/src/test/java/org/kohsuke/AppTest.java index d11428fb63..81c2074eb6 100644 --- a/src/test/java/org/kohsuke/AppTest.java +++ b/src/test/java/org/kohsuke/AppTest.java @@ -3,6 +3,7 @@ import junit.framework.TestCase; import org.kohsuke.github.GHOrganization; import org.kohsuke.github.GHOrganization.Permission; +import org.kohsuke.github.GHPullRequest; import org.kohsuke.github.GHRepository; import org.kohsuke.github.GHTeam; import org.kohsuke.github.GHUser; @@ -21,6 +22,17 @@ public void testCredentialValid() throws IOException { assertFalse(GitHub.connect("totally","bogus").isCredentialValid()); } + public void tryOrgFork() throws Exception { + GitHub gh = GitHub.connect(); + gh.getUser("kohsuke").getRepository("rubywm").forkTo(gh.getOrganization("jenkinsci")); + } + + public void tryGetTeamsForRepo() throws Exception { + GitHub gh = GitHub.connect(); + Set o = gh.getOrganization("jenkinsci").getRepository("rubywm").getTeams(); + System.out.println(o); + } + public void testMembership() throws Exception { GitHub gitHub = GitHub.connect(); Set members = gitHub.getOrganization("jenkinsci").getRepository("violations-plugin").getCollaboratorNames(); @@ -29,6 +41,9 @@ public void testMembership() throws Exception { public void testApp() throws IOException { GitHub gitHub = GitHub.connect(); + GHPullRequest i = gitHub.getOrganization("jenkinsci").getRepository("parameterized-trigger-plugin").getPullRequest(3); + System.out.println(i); + // GHPullRequest i = gitHub.getOrganization("jenkinsci").getRepository("sandbox").getPullRequest(1); // for (GHIssueComment c : i.getComments()) // System.out.println(c);