From 0ad419b026724c61a9d96335347694d0dee019cc Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 26 Oct 2011 17:39:15 -0700 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 82b584aec5..bd43203945 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.14 + 1.15-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java From c86c9744003ae8cd57b2762b78273a4bf84eb434 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Thu, 10 Nov 2011 14:23:36 -0800 Subject: [PATCH 02/11] GHOrganization.createRepository broke, so I fixed that by using V3 API. That didn't quite work because v3 API has owner as an object, whereas v2 API has owner as string. So then I fixed all the other retrieval points for GHRepository to use v3. --- .../org/kohsuke/github/GHOrganization.java | 25 +++---- .../java/org/kohsuke/github/GHPerson.java | 4 +- .../java/org/kohsuke/github/GHRepository.java | 45 +++++++------ src/main/java/org/kohsuke/github/GHTeam.java | 2 +- src/main/java/org/kohsuke/github/GitHub.java | 33 ++++++---- .../org/kohsuke/github/JsonRepository.java | 36 ---------- src/main/java/org/kohsuke/github/Poster.java | 65 ++++++++++++++----- 7 files changed, 107 insertions(+), 103 deletions(-) delete mode 100644 src/main/java/org/kohsuke/github/JsonRepository.java diff --git a/src/main/java/org/kohsuke/github/GHOrganization.java b/src/main/java/org/kohsuke/github/GHOrganization.java index 6aec2259b5..f95e6dd023 100644 --- a/src/main/java/org/kohsuke/github/GHOrganization.java +++ b/src/main/java/org/kohsuke/github/GHOrganization.java @@ -12,6 +12,8 @@ import java.util.List; import java.util.Map; +import static org.kohsuke.github.ApiVersion.V3; + /** * @author Kohsuke Kawaguchi */ @@ -23,23 +25,14 @@ public class GHOrganization extends GHPerson { * Newly created repository. */ public GHRepository createRepository(String name, String description, String homepage, String team, boolean isPublic) throws IOException { - // such API doesn't exist, so fall back to HTML scraping - WebClient wc = root.createWebClient(); - HtmlPage pg = (HtmlPage)wc.getPage("https://github.com/organizations/"+login+"/repositories/new"); - HtmlForm f = pg.getForms().get(1); - f.getInputByName("repository[name]").setValueAttribute(name); - f.getInputByName("repository[description]").setValueAttribute(description); - f.getInputByName("repository[homepage]").setValueAttribute(homepage); - f.getSelectByName("team_id").getOptionByText(team).setSelected(true); - f.submit(f.getButtonByCaption("Create Repository")); - - return getRepository(name); + return createRepository(name,description,homepage,getTeams().get(team),isPublic); + } -// GHRepository r = new Poster(root).withCredential() -// .with("name", name).with("description", description).with("homepage", homepage) -// .with("public", isPublic ? 1 : 0).to(root.getApiURL("/organizations/"+login+"/repos/create"), JsonRepository.class).repository; -// r.root = root; -// return r; + public GHRepository createRepository(String name, String description, String homepage, GHTeam team, boolean isPublic) throws IOException { + // such API doesn't exist, so fall back to HTML scraping + return new Poster(root,V3).withCredential() + .with("name", name).with("description", description).with("homepage", homepage) + .with("public", isPublic).with("team_id",team.getId()).to("/orgs/"+login+"/repos", GHRepository.class).wrap(root); } /** diff --git a/src/main/java/org/kohsuke/github/GHPerson.java b/src/main/java/org/kohsuke/github/GHPerson.java index 625ae03d1e..60f852f0cf 100644 --- a/src/main/java/org/kohsuke/github/GHPerson.java +++ b/src/main/java/org/kohsuke/github/GHPerson.java @@ -23,7 +23,7 @@ public abstract class GHPerson { public synchronized Map getRepositories() throws IOException { Map repositories = new TreeMap(); for (int i=1; ; i++) { - Map map = root.retrieve("/repos/show/" + login + "?page=" + i, JsonRepositories.class).wrap(root); + Map map = root.retrieve3("/user/" + login + "/repos?per_page=100&page=" + i, JsonRepositories.class).wrap(root); repositories.putAll(map); if (map.isEmpty()) break; } @@ -32,7 +32,7 @@ public synchronized Map getRepositories() throws IOExceptio } public GHRepository getRepository(String name) throws IOException { - return root.retrieve("/repos/show/" + login + '/' + name, JsonRepository.class).wrap(root); + return root.retrieve3("/repos/" + login + '/' + name, GHRepository.class).wrap(root); } /** diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index db1d37e18d..2916ac01ae 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -59,7 +59,8 @@ public class GHRepository { /*package almost final*/ GitHub root; - private String description, homepage, url, name, owner; + private String description, homepage, url, name; + private GHUser owner; // not fully populated. beware. private boolean has_issues, has_wiki, fork, _private, has_downloads; private int watchers,forks,open_issues; private String created_at, pushed_at; @@ -84,15 +85,15 @@ public String getName() { } public GHUser getOwner() throws IOException { - return root.getUser(owner); + return root.getUser(owner.login); // because 'owner' isn't fully populated } public List getIssues(GHIssueState state) throws IOException { - return root.retrieve("/issues/list/" + owner + "/" + name + "/" + state.toString().toLowerCase(), JsonIssues.class).wrap(this); + return root.retrieve("/issues/list/" + owner.login + "/" + name + "/" + state.toString().toLowerCase(), JsonIssues.class).wrap(this); } protected String getOwnerName() { - return owner; + return owner.login; } public boolean hasIssues() { @@ -142,7 +143,7 @@ public Date getCreatedAt() { */ public Set getCollaborators() throws IOException { Set r = new HashSet(); - for (String u : root.retrieve("/repos/show/"+owner+"/"+name+"/collaborators",JsonCollaborators.class).collaborators) + for (String u : root.retrieve("/repos/show/"+owner.login+"/"+name+"/collaborators",JsonCollaborators.class).collaborators) r.add(root.getUser(u)); return Collections.unmodifiableSet(r); } @@ -152,7 +153,7 @@ public Set getCollaborators() throws IOException { * This method deviates from the principle of this library but it works a lot faster than {@link #getCollaborators()}. */ public Set getCollaboratorNames() throws IOException { - Set r = new HashSet(root.retrieve("/repos/show/"+owner+"/"+name+"/collaborators",JsonCollaborators.class).collaborators); + Set r = new HashSet(root.retrieve("/repos/show/"+owner.login+"/"+name+"/collaborators",JsonCollaborators.class).collaborators); return Collections.unmodifiableSet(r); } @@ -160,8 +161,8 @@ 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.retrieveWithAuth("/repos/show/"+owner+"/"+name+"/teams",JsonTeams.class).toSet( - root.getOrganization(owner))); + return Collections.unmodifiableSet(root.retrieveWithAuth("/repos/show/"+owner.login+"/"+name+"/teams",JsonTeams.class).toSet( + root.getOrganization(owner.login))); } public void addCollaborators(GHUser... users) throws IOException { @@ -204,7 +205,7 @@ public void setEmailServiceHook(String address) throws IOException { */ public void enableIssueTracker(boolean v) throws IOException { new Poster(root).withCredential().with("values[has_issues]",String.valueOf(v)) - .to("/repos/show/" + owner + "/" + name); + .to("/repos/show/" + owner.login + "/" + name); } /** @@ -212,7 +213,7 @@ public void enableIssueTracker(boolean v) throws IOException { */ public void enableWiki(boolean v) throws IOException { new Poster(root).withCredential().with("values[has_wiki]",String.valueOf(v)) - .to("/repos/show/" + owner + "/" + name); + .to("/repos/show/" + owner.login + "/" + name); } /** @@ -220,7 +221,7 @@ public void enableWiki(boolean v) throws IOException { */ public void delete() throws IOException { Poster poster = new Poster(root).withCredential(); - String url = "/repos/delete/" + owner +"/"+name; + String url = "/repos/delete/" + owner.login +"/"+name; DeleteToken token = poster.to(url, DeleteToken.class); poster.with("delete_token",token.delete_token).to(url); @@ -233,7 +234,7 @@ public void delete() throws IOException { * Newly forked repository that belong to you. */ public GHRepository fork() throws IOException { - return new Poster(root).withCredential().to("/repos/fork/" + owner + "/" + name, JsonRepository.class).wrap(root); + return new Poster(root,V3).withCredential().to("/repos/" + owner.login + "/" + name + "/forks", GHRepository.class, "POST").wrap(root); } /** @@ -243,7 +244,7 @@ public GHRepository fork() throws IOException { * Newly forked repository that belong to you. */ public GHRepository forkTo(GHOrganization org) throws IOException { - new Poster(root, V3).withCredential().to(String.format("/repos/%s/%s/forks?org=%s",owner,name,org.getLogin())); + new Poster(root, V3).withCredential().to(String.format("/repos/%s/%s/forks?org=%s",owner.login,name,org.getLogin())); return org.getRepository(name); } @@ -277,21 +278,21 @@ public void renameTo(String newName) throws IOException { } } - throw new IllegalArgumentException("Either you don't have the privilege to rename "+owner+'/'+name+" or there's a bug in HTML scraping"); + throw new IllegalArgumentException("Either you don't have the privilege to rename "+owner.login+'/'+name+" or there's a bug in HTML scraping"); } /** * Retrieves a specified pull request. */ public GHPullRequest getPullRequest(int i) throws IOException { - return root.retrieveWithAuth("/pulls/" + owner + '/' + name + "/" + i, JsonPullRequest.class).wrap(this); + return root.retrieveWithAuth("/pulls/" + owner.login + '/' + name + "/" + i, JsonPullRequest.class).wrap(this); } /** * Retrieves all the pull requests of a particular state. */ public List getPullRequests(GHIssueState state) throws IOException { - return root.retrieveWithAuth("/pulls/"+owner+'/'+name+"/"+state.name().toLowerCase(Locale.ENGLISH),JsonPullRequests.class).wrap(this); + return root.retrieveWithAuth("/pulls/"+owner.login+'/'+name+"/"+state.name().toLowerCase(Locale.ENGLISH),JsonPullRequests.class).wrap(this); } // this is no different from getPullRequests(OPEN) @@ -303,8 +304,8 @@ public List getPullRequests(GHIssueState state) throws IOExceptio // } private void verifyMine() throws IOException { - if (!root.login.equals(owner)) - throw new IOException("Operation not applicable to a repository owned by someone else: "+owner); + if (!root.login.equals(owner.login)) + throw new IOException("Operation not applicable to a repository owned by someone else: "+owner.login); } /** @@ -406,10 +407,14 @@ private HtmlForm getForm() throws IOException { } }; + /*package*/ GHRepository wrap(GitHub root) { + this.root = root; + return this; + } @Override public String toString() { - return "Repository:"+owner+":"+name; + return "Repository:"+owner.login+":"+name; } @Override @@ -421,7 +426,7 @@ public int hashCode() { public boolean equals(Object obj) { if (obj instanceof GHRepository) { GHRepository that = (GHRepository) obj; - return this.owner.equals(that.owner) + return this.owner.login.equals(that.owner.login) && this.name.equals(that.name); } return false; diff --git a/src/main/java/org/kohsuke/github/GHTeam.java b/src/main/java/org/kohsuke/github/GHTeam.java index dee87bc4e3..a9443acb08 100644 --- a/src/main/java/org/kohsuke/github/GHTeam.java +++ b/src/main/java/org/kohsuke/github/GHTeam.java @@ -35,7 +35,7 @@ public Set getMembers() throws IOException { } public Map getRepositories() throws IOException { - return org.root.retrieveWithAuth(api("/repositories"),JsonRepositories.class).wrap(org.root); + return org.root.retrieveWithAuth3(api("/repos"),JsonRepositories.class).wrap(org.root); } /** diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 8eb543b949..3df9a2968f 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -35,6 +35,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; import java.io.InterruptedIOException; import java.net.HttpURLConnection; @@ -42,15 +43,13 @@ import java.net.URL; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.util.Collections; import java.util.Date; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; import java.util.Properties; -import java.util.Set; import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.*; +import static org.kohsuke.github.ApiVersion.*; /** * Root of the GitHub API. @@ -141,22 +140,30 @@ public static GitHub connectAnonymously() { } /*package*/ T retrieve(String tailApiUrl, Class type) throws IOException { - return _retrieve(tailApiUrl, type, "GET", false); + return _retrieve(tailApiUrl, type, "GET", false, V2); + } + + /*package*/ T retrieve3(String tailApiUrl, Class type) throws IOException { + return _retrieve(tailApiUrl, type, "GET", false, V3); } /*package*/ T retrieveWithAuth(String tailApiUrl, Class type) throws IOException { return retrieveWithAuth(tailApiUrl,type,"GET"); } + /*package*/ T retrieveWithAuth3(String tailApiUrl, Class type) throws IOException { + return _retrieve(tailApiUrl, type, "GET", true, V3); + } + /*package*/ T retrieveWithAuth(String tailApiUrl, Class type, String method) throws IOException { - return _retrieve(tailApiUrl, type, method, true); + return _retrieve(tailApiUrl, type, method, true, V2); } - private T _retrieve(String tailApiUrl, Class type, String method, boolean withAuth) throws IOException { + private T _retrieve(String tailApiUrl, Class type, String method, boolean withAuth, ApiVersion v) throws IOException { while (true) {// loop while API rate limit is hit - HttpURLConnection uc = (HttpURLConnection) getApiURL(ApiVersion.V2,tailApiUrl).openConnection(); + HttpURLConnection uc = (HttpURLConnection) getApiURL(v,tailApiUrl).openConnection(); if (withAuth && this.oauthAccessToken == null) uc.setRequestProperty("Authorization", "Basic " + encodedAuthorization); @@ -190,8 +197,12 @@ private T _retrieve(String tailApiUrl, Class type, String method, boolean throw (InterruptedIOException)new InterruptedIOException().initCause(e); } } - - throw (IOException)new IOException(IOUtils.toString(uc.getErrorStream(),"UTF-8")).initCause(e); + + InputStream es = uc.getErrorStream(); + if (es!=null) + throw (IOException)new IOException(IOUtils.toString(es,"UTF-8")).initCause(e); + else + throw e; } /** @@ -258,9 +269,9 @@ public GHUser getMyself() throws IOException { * Newly created repository. */ public GHRepository createRepository(String name, String description, String homepage, boolean isPublic) throws IOException { - return new Poster(this).withCredential() + return new Poster(this,V3).withCredential() .with("name", name).with("description", description).with("homepage", homepage) - .with("public", isPublic ? 1 : 0).to("/repos/create", JsonRepository.class).wrap(this); + .with("public", isPublic ? 1 : 0).to("/user/repos", GHRepository.class,"POST").wrap(this); } /** diff --git a/src/main/java/org/kohsuke/github/JsonRepository.java b/src/main/java/org/kohsuke/github/JsonRepository.java deleted file mode 100644 index eb8eadd315..0000000000 --- a/src/main/java/org/kohsuke/github/JsonRepository.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2010, Kohsuke Kawaguchi - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.kohsuke.github; - -/** - * @author Kohsuke Kawaguchi - */ -class JsonRepository { - public GHRepository repository; - - public GHRepository wrap(GitHub root) { - repository.root = root; - return repository; - } -} diff --git a/src/main/java/org/kohsuke/github/Poster.java b/src/main/java/org/kohsuke/github/Poster.java index 29097a282c..29b024d5de 100644 --- a/src/main/java/org/kohsuke/github/Poster.java +++ b/src/main/java/org/kohsuke/github/Poster.java @@ -24,6 +24,9 @@ package org.kohsuke.github; import org.apache.commons.io.IOUtils; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.impl.WriterBasedGenerator; +import org.codehaus.jackson.node.ObjectNode; import java.io.IOException; import java.io.InputStreamReader; @@ -33,7 +36,9 @@ import java.net.HttpURLConnection; import java.net.URLEncoder; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import static org.kohsuke.github.GitHub.*; @@ -43,11 +48,25 @@ */ class Poster { private final GitHub root; - private final List args = new ArrayList(); + private final List args = new ArrayList(); private boolean authenticate; private final ApiVersion v; + private static class Entry { + String key; + Object value; + + private Entry(String key, Object value) { + this.key = key; + this.value = value; + } + + public String toFormArg() throws UnsupportedEncodingException { + return URLEncoder.encode(key,"UTF-8")+'='+URLEncoder.encode(value.toString(),"UTF-8"); + } + } + Poster(GitHub root, ApiVersion v) { this.root = root; this.v = v; @@ -64,16 +83,20 @@ public Poster withCredential() { } public Poster with(String key, int value) { - return with(key,String.valueOf(value)); + return _with(key, value); + } + + public Poster with(String key, boolean value) { + return _with(key, value); } public Poster with(String key, String value) { + return _with(key, value); + } + + private Poster _with(String key, Object value) { if (value!=null) { - try { - args.add(URLEncoder.encode(key,"UTF-8")+'='+URLEncoder.encode(value,"UTF-8")); - } catch (UnsupportedEncodingException e) { - throw new Error(e); // impossible - } + args.add(new Entry(key,value)); } return this; } @@ -112,23 +135,31 @@ public T to(String tailApiUrl, Class type, String method) throws IOExcept uc.setRequestMethod(method); - StringBuilder body = new StringBuilder(); - for (String e : args) { - if (body.length()>0) body.append('&'); - body.append(e); - } + if (v==ApiVersion.V2) { + StringBuilder body = new StringBuilder(); + for (Entry e : args) { + if (body.length()>0) body.append('&'); + body.append(e.toFormArg()); + } - OutputStreamWriter o = new OutputStreamWriter(uc.getOutputStream(), "UTF-8"); - o.write(body.toString()); - o.close(); + OutputStreamWriter o = new OutputStreamWriter(uc.getOutputStream(), "UTF-8"); + o.write(body.toString()); + o.close(); + } else { + Map json = new HashMap(); + for (Entry e : args) { + json.put(e.key, e.value); + } + MAPPER.writeValue(uc.getOutputStream(),json); + } try { InputStreamReader r = new InputStreamReader(uc.getInputStream(), "UTF-8"); + String data = IOUtils.toString(r); if (type==null) { - String data = IOUtils.toString(r); return null; } - return MAPPER.readValue(r,type); + return MAPPER.readValue(data,type); } catch (IOException e) { root.handleApiError(e,uc); } From f25083fde192526f4dc76e3f279e1c5c30d2ef12 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Thu, 10 Nov 2011 14:25:59 -0800 Subject: [PATCH 03/11] more test --- src/test/java/org/kohsuke/AppTest.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/test/java/org/kohsuke/AppTest.java b/src/test/java/org/kohsuke/AppTest.java index 0c8959e482..55d7d1c35e 100644 --- a/src/test/java/org/kohsuke/AppTest.java +++ b/src/test/java/org/kohsuke/AppTest.java @@ -42,6 +42,9 @@ public void testMembership() throws Exception { public void testApp() throws IOException { GitHub gitHub = GitHub.connect(); +// GHRepository r = gitHub.connect().getOrganization("jenkinsci").createRepository("kktest4", "Kohsuke's test", "http://kohsuke.org/", "Everyone", true); +// r.fork(); + // tryDisablingIssueTrackers(gitHub); // tryDisablingWiki(gitHub); @@ -129,10 +132,13 @@ private void testPostCommitHook(GitHub gitHub) throws IOException { System.out.println(hooks); } - private void testOrganization(GitHub gitHub) throws IOException { - GHOrganization labs = gitHub.getOrganization("HudsonLabs"); - GHTeam t = labs.getTeams().get("Core Developers"); + public void testOrganization() throws IOException { + GitHub gitHub = GitHub.connect(); + GHOrganization j = gitHub.getOrganization("jenkinsci"); + GHTeam t = j.getTeams().get("Core Developers"); + + assertNotNull(j.getRepository("jenkins")); - t.add(labs.getRepository("xyz")); +// t.add(labs.getRepository("xyz")); } } From b8a63541e895c0a665fcc4b572fd41ab225f644a Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Thu, 10 Nov 2011 14:30:27 -0800 Subject: [PATCH 04/11] v3 API changed the meaning of the 'url' field. --- src/main/java/org/kohsuke/github/GHRepository.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 2916ac01ae..44abaca1c3 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -59,7 +59,9 @@ public class GHRepository { /*package almost final*/ GitHub root; - private String description, homepage, url, name; + private String description, homepage, name; + private String url; // this is the API url + private String html_url; // this is the UI private GHUser owner; // not fully populated. beware. private boolean has_issues, has_wiki, fork, _private, has_downloads; private int watchers,forks,open_issues; @@ -77,7 +79,7 @@ public String getHomepage() { * URL of this repository, like 'http://github.com/kohsuke/hudson' */ public String getUrl() { - return url; + return html_url; } public String getName() { From 1c613c5f07a4f1de006b4f4df6c10b9b2836070f Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Tue, 15 Nov 2011 15:19:04 -0800 Subject: [PATCH 05/11] added a method to publicize/conceal --- .../java/org/kohsuke/github/GHOrganization.java | 14 ++++++++++++++ src/main/java/org/kohsuke/github/GitHub.java | 4 ++++ 2 files changed, 18 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHOrganization.java b/src/main/java/org/kohsuke/github/GHOrganization.java index f95e6dd023..6427afbac6 100644 --- a/src/main/java/org/kohsuke/github/GHOrganization.java +++ b/src/main/java/org/kohsuke/github/GHOrganization.java @@ -42,6 +42,20 @@ public Map getTeams() throws IOException { return root.retrieveWithAuth("/organizations/"+login+"/teams",JsonTeams.class).toMap(this); } + /** + * Publicizes the membership. + */ + public void publicize(GHUser u) throws IOException { + root.retrieveWithAuth3("/orgs/"+login+"/public_members/"+u.getLogin(),null,"PUT"); + } + + /** + * Conceals the membership. + */ + public void conceal(GHUser u) throws IOException { + root.retrieveWithAuth3("/orgs/"+login+"/public_members/"+u.getLogin(),null,"DELETE"); + } + public enum Permission { ADMIN, PUSH, PULL } /** diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 3df9a2968f..dcc5579f26 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -159,6 +159,10 @@ public static GitHub connectAnonymously() { return _retrieve(tailApiUrl, type, method, true, V2); } + /*package*/ T retrieveWithAuth3(String tailApiUrl, Class type, String method) throws IOException { + return _retrieve(tailApiUrl, type, method, true, V3); + } + private T _retrieve(String tailApiUrl, Class type, String method, boolean withAuth, ApiVersion v) throws IOException { while (true) {// loop while API rate limit is hit From c8eab1f53e332524bffed356e6d16c8f83ab7617 Mon Sep 17 00:00:00 2001 From: Michael O'Cleirigh Date: Sat, 19 Nov 2011 01:08:01 -0500 Subject: [PATCH 06/11] OAuth related changes to getMyself() and getUser (username) Changed how getMyself() works so that in the OAuth case it will use the username less url. Changed how getUser (username) works in the OAuth case so that you can lookup the specific username using the OAuth token. Previously getUser (username) would always return the 'myself' user. --- src/main/java/org/kohsuke/github/GitHub.java | 73 ++++++++++++-------- 1 file changed, 45 insertions(+), 28 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index dcc5579f26..528d152fc7 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -210,26 +210,50 @@ private T _retrieve(String tailApiUrl, Class type, String method, boolean } /** - * Obtains the object that represents the named user. - */ - public GHUser getUser(String login) throws IOException { - GHUser u = users.get(login); - if (u==null) { - - if (oauthAccessToken != null) { - u = retrieve("/user/show",JsonUser.class).user; - u.root = this; - users.put(u.getLogin(),u); - } - else { - u = retrieve("/user/show/"+login,JsonUser.class).user; - u.root = this; - users.put(login,u); - } - - } - return u; - } + * Gets the {@link GHUser} that represents yourself. + */ + public GHUser getMyself() throws IOException { + requireCredential(); + + GHUser u = null; + + if (oauthAccessToken != null) { + + u = retrieve("/user/show", JsonUser.class).user; + + u.root = this; + users.put(u.getLogin(), u); + + return u; + } + else { + return getUser(login); + } + + + + } + + /** + * Obtains the object that represents the named user. + */ + public GHUser getUser(String login) throws IOException { + GHUser u = users.get(login); + if (u == null) { + + if (oauthAccessToken != null) { + u = retrieve("/user/show/" + login, JsonUser.class).user; + u.root = this; + users.put(u.getLogin(), u); + } else { + u = retrieve("/user/show/" + login, JsonUser.class).user; + u.root = this; + users.put(login, u); + } + + } + return u; + } /** * Interns the given {@link GHUser}. @@ -258,14 +282,7 @@ public Map getMyOrganizations() throws IOException { return retrieveWithAuth("/organizations",JsonOrganizations.class).wrap(this); } - /** - * Gets the {@link GHUser} that represents yourself. - */ - public GHUser getMyself() throws IOException { - requireCredential(); - return getUser(login); - } - + /** * Creates a new repository. * From 11b0ac19fdd50eb38ae027e136c80d66d3a8ebab Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Tue, 15 Nov 2011 15:41:46 -0800 Subject: [PATCH 07/11] PUT apparently requires some payload. --- src/main/java/org/kohsuke/github/GitHub.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 528d152fc7..4527002948 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -173,6 +173,11 @@ private T _retrieve(String tailApiUrl, Class type, String method, boolean uc.setRequestProperty("Authorization", "Basic " + encodedAuthorization); uc.setRequestMethod(method); + if (method.equals("PUT")) { + uc.setDoOutput(true); + uc.setRequestProperty("Content-Length","0"); + uc.getOutputStream().close(); + } try { InputStreamReader r = new InputStreamReader(uc.getInputStream(), "UTF-8"); From 7a3127ed659a71de5680bcde848a5e40601719ea Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Tue, 15 Nov 2011 15:42:28 -0800 Subject: [PATCH 08/11] added a method to list all members --- .../org/kohsuke/github/GHOrganization.java | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHOrganization.java b/src/main/java/org/kohsuke/github/GHOrganization.java index 6427afbac6..96bf191c36 100644 --- a/src/main/java/org/kohsuke/github/GHOrganization.java +++ b/src/main/java/org/kohsuke/github/GHOrganization.java @@ -6,6 +6,7 @@ import com.gargoylesoftware.htmlunit.html.HtmlPage; import java.io.IOException; +import java.util.AbstractList; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -46,14 +47,39 @@ public Map getTeams() throws IOException { * Publicizes the membership. */ public void publicize(GHUser u) throws IOException { - root.retrieveWithAuth3("/orgs/"+login+"/public_members/"+u.getLogin(),null,"PUT"); + root.retrieveWithAuth3("/orgs/" + login + "/public_members/" + u.getLogin(), null, "PUT"); + } + + /** + * All the members of this organization. + */ + public List getMembers() throws IOException { + return new AbstractList() { + // these are shallow objects with only some limited values filled out + // TODO: it's better to allow objects to fill themselves in later when missing values are requested + final GHUser[] shallow = root.retrieveWithAuth3("/orgs/" + login + "/members", GHUser[].class); + + @Override + public GHUser get(int index) { + try { + return root.getUser(shallow[index].getLogin()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public int size() { + return shallow.length; + } + }; } /** * Conceals the membership. */ public void conceal(GHUser u) throws IOException { - root.retrieveWithAuth3("/orgs/"+login+"/public_members/"+u.getLogin(),null,"DELETE"); + root.retrieveWithAuth3("/orgs/" + login + "/public_members/" + u.getLogin(), null, "DELETE"); } public enum Permission { ADMIN, PUSH, PULL } From 1e9a68a16b1eb4851e0a58f36196189d71c80063 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Mon, 19 Dec 2011 17:07:20 -0800 Subject: [PATCH 09/11] fixed the behaviour in case the repository doesn't exist. --- src/main/java/org/kohsuke/github/GHPerson.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHPerson.java b/src/main/java/org/kohsuke/github/GHPerson.java index 60f852f0cf..393c342e35 100644 --- a/src/main/java/org/kohsuke/github/GHPerson.java +++ b/src/main/java/org/kohsuke/github/GHPerson.java @@ -1,5 +1,6 @@ package org.kohsuke.github; +import java.io.FileNotFoundException; import java.io.IOException; import java.util.Collections; import java.util.Map; @@ -31,8 +32,17 @@ public synchronized Map getRepositories() throws IOExceptio return Collections.unmodifiableMap(repositories); } + /** + * + * @return + * null if the repository was not found + */ public GHRepository getRepository(String name) throws IOException { - return root.retrieve3("/repos/" + login + '/' + name, GHRepository.class).wrap(root); + try { + return root.retrieve3("/repos/" + login + '/' + name, GHRepository.class).wrap(root); + } catch (FileNotFoundException e) { + return null; + } } /** From 74415b14be4da869aaa4c20de9dfe2b97d262c02 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Mon, 19 Dec 2011 17:47:08 -0800 Subject: [PATCH 10/11] bug fix in the error handling --- src/main/java/org/kohsuke/github/GitHub.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 4527002948..118f5a538b 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -34,6 +34,7 @@ import java.io.File; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -206,6 +207,9 @@ private T _retrieve(String tailApiUrl, Class type, String method, boolean throw (InterruptedIOException)new InterruptedIOException().initCause(e); } } + + if (e instanceof FileNotFoundException) + throw e; // pass through 404 Not Found to allow the caller to handle it intelligently InputStream es = uc.getErrorStream(); if (es!=null) From 2bee34da590a89ceca4ee922109b76682cc0d48c Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 31 Dec 2011 21:20:00 -0800 Subject: [PATCH 11/11] [maven-release-plugin] prepare release github-api-1.15 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index bd43203945..343fee323e 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.15-SNAPSHOT + 1.15 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java