From 70648651577d4e6314095709b0cfc7a3d1ee23c4 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 5 Jan 2013 17:18:17 -0800 Subject: [PATCH 01/11] [maven-release-plugin] prepare for next development iteration --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b05beb55d0..76204fa53c 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.34 + 1.35-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java From 975ef1a43ded992c1ad521c24cc43708701806a0 Mon Sep 17 00:00:00 2001 From: Johno Crawford Date: Sun, 6 Jan 2013 04:06:55 +0100 Subject: [PATCH 02/11] Removed last traces of web client. --- .gitignore | 1 + pom.xml | 13 +++---------- .../org/kohsuke/github/GHOrganization.java | 15 +++++---------- .../java/org/kohsuke/github/GHRepository.java | 19 ++++--------------- src/main/java/org/kohsuke/github/GitHub.java | 17 +---------------- .../java/org/kohsuke/github/Requester.java | 4 ++++ 6 files changed, 18 insertions(+), 51 deletions(-) diff --git a/.gitignore b/.gitignore index 097367121c..cb9b4d6a4a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ target +.idea/ *.iml *.ipr *.iws diff --git a/pom.xml b/pom.xml index 76204fa53c..331e0eb207 100644 --- a/pom.xml +++ b/pom.xml @@ -44,16 +44,9 @@ - org.jvnet.hudson - htmlunit - 2.6-hudson-2 - - - - xml-apis - xml-apis - - + commons-lang + commons-lang + 2.6 junit diff --git a/src/main/java/org/kohsuke/github/GHOrganization.java b/src/main/java/org/kohsuke/github/GHOrganization.java index 188f26d930..b91037b16f 100644 --- a/src/main/java/org/kohsuke/github/GHOrganization.java +++ b/src/main/java/org/kohsuke/github/GHOrganization.java @@ -1,9 +1,5 @@ package org.kohsuke.github; -import com.gargoylesoftware.htmlunit.WebClient; -import com.gargoylesoftware.htmlunit.html.HtmlAnchor; -import com.gargoylesoftware.htmlunit.html.HtmlPage; - import java.io.IOException; import java.util.AbstractList; import java.util.ArrayList; @@ -112,13 +108,12 @@ public GHTeam createTeam(String name, Permission p, GHRepository... repositories * List up repositories that has some open pull requests. */ public List getRepositoriesWithOpenPullRequests() throws IOException { - WebClient wc = root.createWebClient(); - HtmlPage pg = (HtmlPage)wc.getPage("https://github.com/organizations/"+login+"/dashboard/pulls"); List r = new ArrayList(); - for (HtmlAnchor e : pg.getElementById("js-issue-list").selectNodes(".//UL[@class='smallnav']/LI[not(@class='zeroed')]/A")) { - String a = e.getHrefAttribute(); - String name = a.substring(a.lastIndexOf('/')+1); - r.add(getRepository(name)); + for (GHRepository repository : root.retrieve().to("/orgs/" + login + "/repos", GHRepository[].class)) { + List pullRequests = repository.getPullRequests(GHIssueState.OPEN); + if (pullRequests.size() > 0) { + r.add(repository); + } } return r; } diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 0260bb888a..703ff2378f 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -23,12 +23,6 @@ */ package org.kohsuke.github; -import com.gargoylesoftware.htmlunit.WebClient; -import com.gargoylesoftware.htmlunit.html.HtmlButton; -import com.gargoylesoftware.htmlunit.html.HtmlCheckBoxInput; -import com.gargoylesoftware.htmlunit.html.HtmlForm; -import com.gargoylesoftware.htmlunit.html.HtmlInput; -import com.gargoylesoftware.htmlunit.html.HtmlPage; import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import java.io.IOException; @@ -266,15 +260,10 @@ private void modifyCollaborators(Collection users, String method) throws } public void setEmailServiceHook(String address) throws IOException { - WebClient wc = root.createWebClient(); - HtmlPage pg = (HtmlPage)wc.getPage(getUrl()+"/admin"); - HtmlInput email = (HtmlInput)pg.getElementById("email_address"); - email.setValueAttribute(address); - HtmlCheckBoxInput active = (HtmlCheckBoxInput)pg.getElementById("email[active]"); - active.setChecked(true); - - final HtmlForm f = email.getEnclosingFormOrDie(); - f.submit((HtmlButton) f.getElementsByTagName("button").get(0)); + Map config = new HashMap(); + config.put("address", address); + new Requester(root).method("POST").with("name", "email").with("config", config).with("active", "true") + .to(String.format("/repos/%s/%s/hooks", owner.login, name)); } private void edit(String key, String value) throws IOException { diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 4253d17e86..ea4f1ba67d 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -23,9 +23,6 @@ */ package org.kohsuke.github; -import com.gargoylesoftware.htmlunit.WebClient; -import com.gargoylesoftware.htmlunit.html.HtmlForm; -import com.gargoylesoftware.htmlunit.html.HtmlPage; import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import org.apache.commons.io.IOUtils; import org.codehaus.jackson.map.DeserializationConfig.Feature; @@ -273,7 +270,7 @@ public Map getMyOrganizations() throws IOException { * Public events visible to you. Equivalent of what's displayed on https://github.com/ */ public List getEvents() throws IOException { - // TODO: pagenation + // TODO: pagination GHEventInfo[] events = retrieve().to("/events", GHEventInfo[].class); for (GHEventInfo e : events) e.wrapUp(this); @@ -318,18 +315,6 @@ public boolean isCredentialValid() throws IOException { } } - WebClient createWebClient() throws IOException { - WebClient wc = new WebClient(); - wc.setJavaScriptEnabled(false); - wc.setCssEnabled(false); - HtmlPage pg = (HtmlPage)wc.getPage("https://github.com/login"); - HtmlForm f = pg.getForms().get(0); - f.getInputByName("login").setValueAttribute(login); - f.getInputByName("password").setValueAttribute(password); - f.submit(); - return wc; - } - /*package*/ static URL parseURL(String s) { try { return s==null ? null : new URL(s); diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index c6bf92639c..feaa25e23a 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -107,6 +107,10 @@ public Requester with(String key, Collection value) { return _with(key, value); } + public Requester with(String key, Map value) { + return _with(key, value); + } + public Requester _with(String key, Object value) { if (value!=null) { args.add(new Entry(key,value)); From f0ab946b885c951d03881e8be35cc0b9875b2ca7 Mon Sep 17 00:00:00 2001 From: johnou Date: Sun, 6 Jan 2013 04:27:18 +0100 Subject: [PATCH 03/11] Removed proprietary api usage. --- pom.xml | 5 +++++ src/main/java/org/kohsuke/github/GitHub.java | 5 ++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 331e0eb207..b9125ef229 100644 --- a/pom.xml +++ b/pom.xml @@ -48,6 +48,11 @@ commons-lang 2.6 + + commons-codec + commons-codec + 1.7 + junit junit diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index ea4f1ba67d..a7b2ea8172 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -24,11 +24,11 @@ package org.kohsuke.github; import com.infradna.tool.bridge_method_injector.WithBridgeMethods; +import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.IOUtils; import org.codehaus.jackson.map.DeserializationConfig.Feature; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.introspect.VisibilityChecker.Std; -import sun.misc.BASE64Encoder; import java.io.File; import java.io.FileInputStream; @@ -83,10 +83,9 @@ private GitHub(String apiUrl, String login, String apiToken, String password) { this.apiToken = apiToken; this.password = password; - BASE64Encoder enc = new sun.misc.BASE64Encoder(); if (apiToken!=null || password!=null) { String userpassword = password==null ? (login + "/token" + ":" + apiToken) : (login + ':'+password); - encodedAuthorization = enc.encode(userpassword.getBytes()); + encodedAuthorization = Base64.encodeBase64String(userpassword.getBytes()); } else encodedAuthorization = null; } From 1fe61f72e201865977bcc4e4ee701f125057de4d Mon Sep 17 00:00:00 2001 From: Johno Crawford Date: Sun, 6 Jan 2013 13:08:41 +0100 Subject: [PATCH 04/11] Password is no longer required for api usage. --- src/main/java/org/kohsuke/github/GitHub.java | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index a7b2ea8172..277e52d821 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -56,7 +56,6 @@ public class GitHub { /*package*/ final String login; /*package*/ final String encodedAuthorization; - /*package*/ final String password; /*package*/ final String apiToken; private final Map users = new HashMap(); @@ -75,17 +74,17 @@ private GitHub(String login, String apiToken, String password) { * The URL of GitHub (or GitHub enterprise) API endpoint, such as "https://api.github.com" or * "http://ghe.acme.com/api/v3". Note that GitHub Enterprise has /api/v3 in the URL. * For historical reasons, this parameter still accepts the bare domain name, but that's considered deprecated. + * Password is also considered deprecated as it is no longer required for api usage. */ private GitHub(String apiUrl, String login, String apiToken, String password) { if (apiUrl.endsWith("/")) apiUrl = apiUrl.substring(0, apiUrl.length()-1); // normalize this.apiUrl = apiUrl; this.login = login; this.apiToken = apiToken; - this.password = password; if (apiToken!=null || password!=null) { - String userpassword = password==null ? (login + "/token" + ":" + apiToken) : (login + ':'+password); - encodedAuthorization = Base64.encodeBase64String(userpassword.getBytes()); + String authorization = password==null ? (login + "/token" + ":" + apiToken) : (login + ':'+password); + encodedAuthorization = Base64.encodeBase64String(authorization.getBytes()); } else encodedAuthorization = null; } @@ -93,7 +92,6 @@ private GitHub(String apiUrl, String login, String apiToken, String password) { private GitHub (String apiUrl, String oauthAccessToken) throws IOException { this.apiUrl = apiUrl; - this.password = null; this.encodedAuthorization = null; this.oauthAccessToken = oauthAccessToken; @@ -126,9 +124,6 @@ public static GitHub connect() throws IOException { * For historical reasons, this parameter still accepts the bare domain name, but that's considered deprecated. */ public static GitHub connectToEnterprise(String apiUrl, String login, String apiToken) { - // not exposing password because the login process still assumes https://github.com/ - // if we are to fix this, fix that by getting rid of createWebClient() and replace the e-mail service hook - // with GitHub API. return new GitHub(apiUrl,login,apiToken,null); } From f80cb541d59de7edf1ba67fb0f4aadb1a1540ff7 Mon Sep 17 00:00:00 2001 From: Johno Crawford Date: Sun, 6 Jan 2013 21:11:19 +0100 Subject: [PATCH 05/11] Fix base64 encoding. --- src/main/java/org/kohsuke/github/GitHub.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 277e52d821..e885b89f84 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -84,7 +84,7 @@ private GitHub(String apiUrl, String login, String apiToken, String password) { if (apiToken!=null || password!=null) { String authorization = password==null ? (login + "/token" + ":" + apiToken) : (login + ':'+password); - encodedAuthorization = Base64.encodeBase64String(authorization.getBytes()); + encodedAuthorization = new String(Base64.encodeBase64(authorization.getBytes())); } else encodedAuthorization = null; } From 6e0202fa0b37e2f290b1f31f3ad83adcc4e1cc38 Mon Sep 17 00:00:00 2001 From: Johno Crawford Date: Sun, 6 Jan 2013 13:26:03 +0100 Subject: [PATCH 06/11] Added membership checks. --- .../org/kohsuke/github/GHOrganization.java | 18 ++++++++++++++++++ src/test/java/org/kohsuke/AppTest.java | 10 ++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHOrganization.java b/src/main/java/org/kohsuke/github/GHOrganization.java index b91037b16f..1bbda71c0e 100644 --- a/src/main/java/org/kohsuke/github/GHOrganization.java +++ b/src/main/java/org/kohsuke/github/GHOrganization.java @@ -46,6 +46,24 @@ public Map getTeams() throws IOException { return r; } + public boolean isMember(String user) { + try { + root.retrieve().to("/orgs/" + login + "/members/" + user); + return true; + } catch (IOException ignore) { + return false; + } + } + + public boolean isPublicMember(String user) { + try { + root.retrieve().to("/orgs/" + login + "/public_members/" + user); + return true; + } catch (IOException ignore) { + return false; + } + } + /** * Publicizes the membership. */ diff --git a/src/test/java/org/kohsuke/AppTest.java b/src/test/java/org/kohsuke/AppTest.java index b272ee7a4d..b167c3676f 100644 --- a/src/test/java/org/kohsuke/AppTest.java +++ b/src/test/java/org/kohsuke/AppTest.java @@ -352,4 +352,14 @@ public void testPullRequestPopulate() throws Exception { GHUser u = p.getUser(); assertNotNull(u.getName()); } + + public void testCheckMembership() throws Exception { + GHOrganization j = GitHub.connect().getOrganization("jenkinsci"); + assertTrue(j.isMember("kohsuke")); + } + + public void testCheckPublicMembership() throws Exception { + GHOrganization j = GitHub.connect().getOrganization("jenkinsci"); + assertTrue(j.isPublicMember("kohsuke")); + } } From 560e3c257ac1ec8d1b99a27f04224577e8b14775 Mon Sep 17 00:00:00 2001 From: Johno Crawford Date: Sun, 6 Jan 2013 16:39:27 +0100 Subject: [PATCH 07/11] Refactored test. --- src/test/java/org/kohsuke/AppTest.java | 75 ++++++++++++-------------- 1 file changed, 33 insertions(+), 42 deletions(-) diff --git a/src/test/java/org/kohsuke/AppTest.java b/src/test/java/org/kohsuke/AppTest.java index b167c3676f..667251429e 100644 --- a/src/test/java/org/kohsuke/AppTest.java +++ b/src/test/java/org/kohsuke/AppTest.java @@ -36,23 +36,31 @@ * Unit test for simple App. */ public class AppTest extends TestCase { + + private GitHub gitHub; + + @Override + public void setUp() throws Exception { + super.setUp(); + gitHub = GitHub.connect(); + } + public void testRepoCRUD() throws Exception { - GitHub hub = GitHub.connect(); - GHRepository r = hub.createRepository("github-api-test", "a test repository", "http://github-api.kohsuke.org/", true); + GHRepository r = gitHub.createRepository("github-api-test", "a test repository", "http://github-api.kohsuke.org/", true); r.enableIssueTracker(false); r.enableDownloads(false); r.enableWiki(false); r.renameTo("github-api-test2"); - hub.getMyself().getRepository("github-api-test2").delete(); + gitHub.getMyself().getRepository("github-api-test2").delete(); } public void testCredentialValid() throws IOException { - assertTrue(GitHub.connect().isCredentialValid()); + assertTrue(gitHub.isCredentialValid()); assertFalse(GitHub.connect("totally", "bogus").isCredentialValid()); } public void testIssueWithNoComment() throws IOException { - GHRepository repository = GitHub.connect().getRepository("kohsuke/test"); + GHRepository repository = gitHub.getRepository("kohsuke/test"); List v = repository.getIssue(4).getComments(); System.out.println(v); assertTrue(v.isEmpty()); @@ -63,7 +71,7 @@ public void testIssueWithNoComment() throws IOException { } public void testCreateIssue() throws IOException { - GHUser u = GitHub.connect().getUser("kohsuke"); + GHUser u = gitHub.getUser("kohsuke"); GHRepository r = u.getRepository("test"); GHMilestone someMilestone = r.listMilestones(GHIssueState.CLOSED).iterator().next(); GHIssue o = r.createIssue("testing").body("this is body").assignee(u).label("bug").label("question").milestone(someMilestone).create(); @@ -72,26 +80,24 @@ public void testCreateIssue() throws IOException { } public void testRateLimit() throws IOException { - System.out.println(GitHub.connect().getRateLimit()); + System.out.println(gitHub.getRateLimit()); } public void testMyOrganizations() throws IOException { - Map org = GitHub.connect().getMyOrganizations(); + Map org = gitHub.getMyOrganizations(); assertFalse(org.keySet().contains(null)); System.out.println(org); } public void testFetchPullRequest() throws Exception { - GitHub gh = GitHub.connect(); - GHRepository r = gh.getOrganization("jenkinsci").getRepository("jenkins"); + GHRepository r = gitHub.getOrganization("jenkinsci").getRepository("jenkins"); assertEquals("master",r.getMasterBranch()); r.getPullRequest(1); r.getPullRequests(GHIssueState.OPEN); } public void testFetchPullRequestAsList() throws Exception { - GitHub gh = GitHub.connect(); - GHRepository r = gh.getOrganization("symfony").getRepository("symfony-docs"); + GHRepository r = gitHub.getOrganization("symfony").getRepository("symfony-docs"); assertEquals("master", r.getMasterBranch()); PagedIterable i = r.listPullRequests(GHIssueState.CLOSED); List prs = i.asList(); @@ -100,19 +106,17 @@ public void testFetchPullRequestAsList() throws Exception { } public void testRepoPermissions() throws Exception { - GitHub gh = GitHub.connect(); - GHRepository r = gh.getOrganization("jenkinsci").getRepository("jenkins"); + GHRepository r = gitHub.getOrganization("jenkinsci").getRepository("jenkins"); assertTrue(r.hasPullAccess()); - r = gh.getOrganization("github").getRepository("tire"); + r = gitHub.getOrganization("github").getRepository("tire"); assertFalse(r.hasAdminAccess()); } public void testGetMyself() throws Exception { - GitHub hub = GitHub.connect(); - GHMyself me = hub.getMyself(); + GHMyself me = gitHub.getMyself(); System.out.println(me); - GHUser u = hub.getUser("kohsuke2"); + GHUser u = gitHub.getUser("kohsuke2"); System.out.println(u); for (List lst : me.iterateRepositories(100)) { for (GHRepository r : lst) { @@ -122,36 +126,30 @@ public void testGetMyself() throws Exception { } public void testPublicKeys() throws Exception { - GitHub gh = GitHub.connect(); - List keys = gh.getMyself().getPublicKeys(); + List keys = gitHub.getMyself().getPublicKeys(); System.out.println(keys); } public void tryOrgFork() throws Exception { - GitHub gh = GitHub.connect(); - gh.getUser("kohsuke").getRepository("rubywm").forkTo(gh.getOrganization("jenkinsci")); + gitHub.getUser("kohsuke").getRepository("rubywm").forkTo(gitHub.getOrganization("jenkinsci")); } public void tryGetTeamsForRepo() throws Exception { - GitHub gh = GitHub.connect(); - Set o = gh.getOrganization("jenkinsci").getRepository("rubywm").getTeams(); + Set o = gitHub.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(); System.out.println(members.contains("kohsuke")); } public void testMemberOrgs() throws Exception { - GitHub gitHub = GitHub.connect(); Set o = gitHub.getUser("kohsuke").getOrganizations(); System.out.println(o); } public void testCommit() throws Exception { - GitHub gitHub = GitHub.connect(); GHCommit commit = gitHub.getUser("jenkinsci").getRepository("jenkins").getCommit("08c1c9970af4d609ae754fbe803e06186e3206f7"); System.out.println(commit); assertEquals(1, commit.getParents().size()); @@ -164,7 +162,6 @@ public void testCommit() throws Exception { } public void testListCommits() throws Exception { - GitHub gitHub = GitHub.connect(); List sha1 = new ArrayList(); for (GHCommit c : gitHub.getUser("kohsuke").getRepository("empty-commit").listCommits()) { System.out.println(c.getSHA1()); @@ -175,14 +172,12 @@ public void testListCommits() throws Exception { } public void testBranches() throws Exception { - GitHub gitHub = GitHub.connect(); Map b = gitHub.getUser("jenkinsci").getRepository("jenkins").getBranches(); System.out.println(b); } public void testCommitComment() throws Exception { - GitHub gitHub = GitHub.connect(); GHRepository r = gitHub.getUser("jenkinsci").getRepository("jenkins"); PagedIterable comments = r.listCommitComments(); List batch = comments.iterator().nextPage(); @@ -193,7 +188,6 @@ public void testCommitComment() throws Exception { } public void testCreateCommitComment() throws Exception { - GitHub gitHub = GitHub.connect(); GHCommit commit = gitHub.getUser("kohsuke").getRepository("sandbox-ant").getCommit("8ae38db0ea5837313ab5f39d43a6f73de3bd9000"); GHCommitComment c = commit.createComment("[testing](http://kohsuse.org/)"); System.out.println(c); @@ -203,7 +197,6 @@ public void testCreateCommitComment() throws Exception { } public void tryHook() throws Exception { - GitHub gitHub = GitHub.connect(); GHRepository r = gitHub.getMyself().getRepository("test2"); GHHook hook = r.createWebHook(new URL("http://www.google.com/")); System.out.println(hook); @@ -213,7 +206,6 @@ public void tryHook() throws Exception { } public void testEventApi() throws Exception { - GitHub gitHub = GitHub.connect(); for (GHEventInfo ev : gitHub.getEvents()) { System.out.println(ev); if (ev.getType()==GHEvent.PULL_REQUEST) { @@ -225,10 +217,9 @@ public void testEventApi() throws Exception { } public void testApp() throws IOException { - GitHub gitHub = GitHub.connect(); System.out.println(gitHub.getMyself().getEmails()); -// GHRepository r = gitHub.connect().getOrganization("jenkinsci").createRepository("kktest4", "Kohsuke's test", "http://kohsuke.org/", "Everyone", true); +// GHRepository r = gitHub.getOrganization("jenkinsci").createRepository("kktest4", "Kohsuke's test", "http://kohsuke.org/", "Everyone", true); // r.fork(); // tryDisablingIssueTrackers(gitHub); @@ -255,7 +246,7 @@ public void testApp() throws IOException { // t.remove(gitHub.getMyself()); // System.out.println(t.getMembers()); -// GHRepository r = GitHub.connect().getOrganization("HudsonLabs").createRepository("auto-test", "some description", "http://kohsuke.org/", "Plugin Developers", true); +// GHRepository r = gitHub.getOrganization("HudsonLabs").createRepository("auto-test", "some description", "http://kohsuke.org/", "Plugin Developers", true); // r. // GitHub hub = GitHub.connectAnonymously(); @@ -314,7 +305,6 @@ private void testPostCommitHook(GitHub gitHub) throws IOException { } public void testOrgRepositories() throws IOException { - GitHub gitHub = GitHub.connect(); GHOrganization j = gitHub.getOrganization("jenkinsci"); long start = System.currentTimeMillis(); Map repos = j.getRepositories(); @@ -323,7 +313,6 @@ public void testOrgRepositories() throws IOException { } public void testOrganization() throws IOException { - GitHub gitHub = GitHub.connect(); GHOrganization j = gitHub.getOrganization("jenkinsci"); GHTeam t = j.getTeams().get("Core Developers"); @@ -333,7 +322,6 @@ public void testOrganization() throws IOException { } public void testCommitStatus() throws Exception { - GitHub gitHub = GitHub.connect(); GHRepository r = gitHub.getUser("kohsuke").getRepository("test"); GHCommitStatus state; // state = r.createCommitStatus("edacdd76b06c5f3f0697a22ca75803169f25f296", GHCommitState.FAILURE, "http://jenkins-ci.org/", "oops!"); @@ -346,20 +334,23 @@ public void testCommitStatus() throws Exception { } public void testPullRequestPopulate() throws Exception { - GitHub gitHub = GitHub.connect(); GHRepository r = gitHub.getUser("kohsuke").getRepository("github-api"); GHPullRequest p = r.getPullRequest(17); GHUser u = p.getUser(); assertNotNull(u.getName()); } + // GitHub usernames may only contain alphanumeric characters or dashes and cannot begin with a dash + public void testCheckMembership() throws Exception { - GHOrganization j = GitHub.connect().getOrganization("jenkinsci"); + GHOrganization j = gitHub.getOrganization("jenkinsci"); assertTrue(j.isMember("kohsuke")); + assertFalse(j.isMember("-kohsuke@#$!")); } public void testCheckPublicMembership() throws Exception { - GHOrganization j = GitHub.connect().getOrganization("jenkinsci"); + GHOrganization j = gitHub.getOrganization("jenkinsci"); assertTrue(j.isPublicMember("kohsuke")); + assertFalse(j.isPublicMember("-kohsuke@#$!")); } } From 2e074b5bc4ccdfe94a9d2108e9ed80c71b9c3280 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sun, 6 Jan 2013 16:24:28 -0800 Subject: [PATCH 08/11] follow up fix to the pull request #28 --- .../org/kohsuke/github/GHOrganization.java | 14 +++++++++---- src/main/java/org/kohsuke/github/GHUser.java | 14 +++++++++++++ src/test/java/org/kohsuke/AppTest.java | 20 +++++++++---------- 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHOrganization.java b/src/main/java/org/kohsuke/github/GHOrganization.java index 1bbda71c0e..a27497fcc0 100644 --- a/src/main/java/org/kohsuke/github/GHOrganization.java +++ b/src/main/java/org/kohsuke/github/GHOrganization.java @@ -46,18 +46,24 @@ public Map getTeams() throws IOException { return r; } - public boolean isMember(String user) { + /** + * Checks if this organization has the specified user as a member. + */ + public boolean hasMember(GHUser user) { try { - root.retrieve().to("/orgs/" + login + "/members/" + user); + root.retrieve().to("/orgs/" + login + "/members/" + user.getLogin()); return true; } catch (IOException ignore) { return false; } } - public boolean isPublicMember(String user) { + /** + * Checks if this organization has the specified user as a public member. + */ + public boolean hasPublicMember(GHUser user) { try { - root.retrieve().to("/orgs/" + login + "/public_members/" + user); + root.retrieve().to("/orgs/" + login + "/public_members/" + user.getLogin()); return true; } catch (IOException ignore) { return false; diff --git a/src/main/java/org/kohsuke/github/GHUser.java b/src/main/java/org/kohsuke/github/GHUser.java index 41fe9a24bb..fb43cbd6d3 100644 --- a/src/main/java/org/kohsuke/github/GHUser.java +++ b/src/main/java/org/kohsuke/github/GHUser.java @@ -69,6 +69,20 @@ public GHPersonSet getFollowers() throws IOException { return new GHPersonSet(Arrays.asList(wrap(followers,root))); } + /** + * Returns true if this user belongs to the specified organization. + */ + public boolean isMemberOf(GHOrganization org) { + return org.hasMember(this); + } + + /** + * Returns true if this user belongs to the specified organization as a public member. + */ + public boolean isPublicMemberOf(GHOrganization org) { + return org.hasPublicMember(this); + } + /*package*/ static GHUser[] wrap(GHUser[] users, GitHub root) { for (GHUser f : users) f.root = root; diff --git a/src/test/java/org/kohsuke/AppTest.java b/src/test/java/org/kohsuke/AppTest.java index 667251429e..efe3dc4ae1 100644 --- a/src/test/java/org/kohsuke/AppTest.java +++ b/src/test/java/org/kohsuke/AppTest.java @@ -67,7 +67,7 @@ public void testIssueWithNoComment() throws IOException { v = repository.getIssue(3).getComments(); System.out.println(v); - assertTrue(v.size()==3); + assertTrue(v.size() == 3); } public void testCreateIssue() throws IOException { @@ -158,7 +158,7 @@ public void testCommit() throws Exception { File f = commit.getFiles().get(0); assertEquals(48,f.getLinesChanged()); assertEquals("modified",f.getStatus()); - assertEquals("changelog.html",f.getFileName()); + assertEquals("changelog.html", f.getFileName()); } public void testListCommits() throws Exception { @@ -340,17 +340,15 @@ public void testPullRequestPopulate() throws Exception { assertNotNull(u.getName()); } - // GitHub usernames may only contain alphanumeric characters or dashes and cannot begin with a dash - public void testCheckMembership() throws Exception { GHOrganization j = gitHub.getOrganization("jenkinsci"); - assertTrue(j.isMember("kohsuke")); - assertFalse(j.isMember("-kohsuke@#$!")); - } + GHUser kohsuke = gitHub.getUser("kohsuke"); + GHUser a = gitHub.getUser("a"); - public void testCheckPublicMembership() throws Exception { - GHOrganization j = gitHub.getOrganization("jenkinsci"); - assertTrue(j.isPublicMember("kohsuke")); - assertFalse(j.isPublicMember("-kohsuke@#$!")); + assertTrue(j.hasMember(kohsuke)); + assertFalse(j.hasMember(a)); + + assertTrue(j.hasPublicMember(kohsuke)); + assertFalse(j.hasPublicMember(a)); } } From 45286598aaf739347844bedacdaa33baaf0af703 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sun, 6 Jan 2013 16:43:43 -0800 Subject: [PATCH 09/11] adding OAuth support in ~/.github --- src/main/java/org/kohsuke/github/GitHub.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index e885b89f84..a24fac3f5c 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -55,6 +55,8 @@ */ public class GitHub { /*package*/ final String login; + + /*package*/ final String encodedAuthorization; /*package*/ final String apiToken; @@ -65,7 +67,7 @@ public class GitHub { private final String apiUrl; private GitHub(String login, String apiToken, String password) { - this ("https://api.github.com", login, apiToken, password); + this (GITHUB_URL, login, apiToken, password); } /** @@ -112,7 +114,11 @@ public static GitHub connect() throws IOException { } finally { IOUtils.closeQuietly(in); } - return new GitHub(props.getProperty("login"),props.getProperty("token"),props.getProperty("password")); + String oauth = props.getProperty("oauth"); + if (oauth!=null) + return new GitHub(GITHUB_URL,oauth); + else + return new GitHub(props.getProperty("login"),props.getProperty("token"),props.getProperty("password")); } /** @@ -164,7 +170,7 @@ public static GitHub connectAnonymously() { if (tailApiUrl.startsWith("/")) { if ("github.com".equals(apiUrl)) {// backward compatibility - return new URL("https://api.github.com" + tailApiUrl); + return new URL(GITHUB_URL + tailApiUrl); } else { return new URL(apiUrl + tailApiUrl); } @@ -339,4 +345,6 @@ public boolean isCredentialValid() throws IOException { MAPPER.setVisibilityChecker(new Std(NONE, NONE, NONE, NONE, ANY)); MAPPER.getDeserializationConfig().set(Feature.FAIL_ON_UNKNOWN_PROPERTIES, false); } + + private static final String GITHUB_URL = "https://api.github.com"; } From 887ca772e0a7e82704255ccf51f0696dafbf800f Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sun, 6 Jan 2013 16:45:17 -0800 Subject: [PATCH 10/11] switching to Markdown --- pom.xml | 2 +- src/site/apt/index.apt | 25 ------------------------- src/site/markdown/index.md | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 26 deletions(-) delete mode 100644 src/site/apt/index.apt create mode 100644 src/site/markdown/index.md diff --git a/pom.xml b/pom.xml index b9125ef229..5f6973bb58 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.kohsuke pom - 3 + 4 github-api diff --git a/src/site/apt/index.apt b/src/site/apt/index.apt deleted file mode 100644 index 28254de23e..0000000000 --- a/src/site/apt/index.apt +++ /dev/null @@ -1,25 +0,0 @@ -What is this? - - This library defines an object oriented representation of the GitHub API. The library doesn't yet cover the entirety of the GitHub API, but it's implemented with the right abstractions and libraries to make it very easy to improve the coverage. - -Sample Usage - ------------------- -GitHub github = GitHub.connect(); -GHRepository repo = github.createRepository( - "new-repository","this is my new repository", - "http://www.kohsuke.org/",true/*public*/); -repo.addCollaborators(github.getUser("abayer"),github.getUser("rtyler")); -repo.delete(); ------------------- - -Credential - - This library allows the caller to supply the credential as parameters, but it also defines a common convention - so that applications using this library will look at the consistent location. In this convention, the library - looks at "~/.github" property file, which should have the following two values: - ------------------- -login=kohsuke -token=012345678 ------------------- diff --git a/src/site/markdown/index.md b/src/site/markdown/index.md new file mode 100644 index 0000000000..ba9fbb5287 --- /dev/null +++ b/src/site/markdown/index.md @@ -0,0 +1,36 @@ +What is this? +===== + +This library defines an object oriented representation of the GitHub API. By "object oriented" we mean +there are classes that correspond to the domain model of GitHub (such as `GHUser` and `GHRepository`), +operations that act on them as defined as methods (such as `GHUser.follow()`), and those object references +are used in favor of using string handle (such as `GHUser.isMemberOf(GHOrganization)` instead of +`GHUser.isMemberOf(String)`) + +There are some corners of the GitHub API that's not yet implemented, but +the library is implemented with the right abstractions and libraries to make it very easy to improve the coverage. + +Sample Usage +----- + + GitHub github = GitHub.connect(); + GHRepository repo = github.createRepository( + "new-repository","this is my new repository", + "http://www.kohsuke.org/",true/*public*/); + repo.addCollaborators(github.getUser("abayer"),github.getUser("rtyler")); + repo.delete(); + +Credential +---- + +This library allows the caller to supply the credential as parameters, but it also defines a common convention +so that applications using this library will look at the consistent location. In this convention, the library +looks at `~/.github` property file, which should have the following two values: + + login=kohsuke + password=012345678 + +Alternatively, you can have just the OAuth token in this file: + + oauth=4d98173f7c075527cb64878561d1fe70 + From 9d75913005100d181bca2b1cb5c6e9620850409f Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sun, 6 Jan 2013 16:47:24 -0800 Subject: [PATCH 11/11] [maven-release-plugin] prepare release github-api-1.35 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5f6973bb58..41e1a14fb6 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.35-SNAPSHOT + 1.35 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java