From c784ab6632dadbeae8b43a99438e78a7c31244b1 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 10 May 2014 13:52:36 -0700 Subject: [PATCH] Added Gist support --- src/main/java/org/kohsuke/github/GHGist.java | 164 ++++++++++++++++++ .../org/kohsuke/github/GHGistBuilder.java | 47 +++++ src/main/java/org/kohsuke/github/GHUser.java | 17 ++ src/main/java/org/kohsuke/github/GitHub.java | 11 ++ .../java/org/kohsuke/github/Requester.java | 65 ++++--- 5 files changed, 282 insertions(+), 22 deletions(-) create mode 100644 src/main/java/org/kohsuke/github/GHGist.java create mode 100644 src/main/java/org/kohsuke/github/GHGistBuilder.java diff --git a/src/main/java/org/kohsuke/github/GHGist.java b/src/main/java/org/kohsuke/github/GHGist.java new file mode 100644 index 000000000..ee8f0023e --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHGist.java @@ -0,0 +1,164 @@ +package org.kohsuke.github; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.io.IOException; +import java.util.Date; + +/** + * Gist + * + * @author Kohsuke Kawaguchi + * @see GHUser#listGists() + * @see GitHub#getGist(String) + */ +public final class GHGist { + /*package almost final*/ GHUser owner; + /*package almost final*/ GitHub root; + + private String url, forks_url, commits_url, id, git_pull_url, git_push_url, html_url; + + @JsonProperty("public") + private boolean _public; + + private String created_at, updated_at, description; + + private int comments; + + private String comments_url; + + /** + * User that owns this Gist. + */ + public GHUser getOwner() { + return owner; + } + + /** + * API URL of this gist, such as 'https://api.github.com/gists/12345' + */ + public String getUrl() { + return url; + } + + public String getForksUrl() { + return forks_url; + } + + public String getCommitsUrl() { + return commits_url; + } + + /** + * ID of this gist, such as '12345' + */ + public String getId() { + return id; + } + + /** + * URL like https://gist.github.com/gists/12345.git + */ + public String getGitPullUrl() { + return git_pull_url; + } + + public String getGitPushUrl() { + return git_push_url; + } + + public String getHtmlUrl() { + return html_url; + } + + public boolean isPublic() { + return _public; + } + + public Date getCreatedAt() { + return GitHub.parseDate(created_at); + } + + public Date getUpdatedAt() { + return GitHub.parseDate(updated_at); + } + + public String getDescription() { + return description; + } + + public int getCommentCount() { + return comments; + } + + /** + * API URL of listing comments. + */ + public String getCommentsUrl() { + return comments_url; + } + + /*package*/ GHGist wrapUp(GHUser owner) { + this.owner = owner; + this.root = owner.root; + return this; + } + + /** + * Used when caller obtains {@link GHGist} without knowing its owner. + * A partially constructed owner object is interned. + */ + /*package*/ GHGist wrapUp(GitHub root) throws IOException { + this.owner = root.getUser(owner); + this.root = root; + return this; + } + + String getApiTailUrl(String tail) { + return "/gist/" + id + '/' + tail; + } + + public void star() throws IOException { + new Requester(root).method("PUT").to(getApiTailUrl("star")); + } + + public void unstar() throws IOException { + new Requester(root).method("DELETE").to(getApiTailUrl("star")); + } + + public boolean isStarred() throws IOException { + return root.retrieve().asHttpStatusCode(getApiTailUrl("star"))/100==2; + } + + /** + * Forks this gist into your own. + */ + public GHGist fork() throws IOException { + return new Requester(root).to(getApiTailUrl("forks"),GHGist.class).wrapUp(root); + } + + public PagedIterable listForks() { + return new PagedIterable() { + public PagedIterator iterator() { + return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("forks"), GHGist[].class)) { + @Override + protected void wrapUp(GHGist[] page) { + try { + for (GHGist c : page) + c.wrapUp(root); + } catch (IOException e) { + throw new Error(e); + } + } + }; + } + }; + } + + /** + * Deletes this gist. + */ + public void delete() throws IOException { + new Requester(root).method("DELETE").to("/gist/" + id); + } +} diff --git a/src/main/java/org/kohsuke/github/GHGistBuilder.java b/src/main/java/org/kohsuke/github/GHGistBuilder.java new file mode 100644 index 000000000..ab2fb51c1 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHGistBuilder.java @@ -0,0 +1,47 @@ +package org.kohsuke.github; + +import java.io.IOException; +import java.util.Collections; +import java.util.LinkedHashMap; + +/** + * Builder pattern for creating a new Gist. + * + * @author Kohsuke Kawaguchi + * @see GitHub#createGist() + */ +public class GHGistBuilder { + private final GitHub root; + private final Requester req; + private final LinkedHashMap files = new LinkedHashMap(); + + public GHGistBuilder(GitHub root) { + this.root = root; + req = new Requester(root); + } + + public GHGistBuilder description(String desc) { + req.with("description",desc); + return this; + } + + public GHGistBuilder public_(boolean v) { + req.with("public",v); + return this; + } + + /** + * Adds a new file. + */ + public GHGistBuilder file(String fileName, String content) { + files.put(fileName, Collections.singletonMap("content", content)); + return this; + } + + /** + * Creates a Gist based on the parameters specified thus far. + */ + public GHGist create() throws IOException { + return req.to("/gists",GHGist.class).wrapUp(root); + } +} diff --git a/src/main/java/org/kohsuke/github/GHUser.java b/src/main/java/org/kohsuke/github/GHUser.java index 55c528e3b..7ebd356d9 100644 --- a/src/main/java/org/kohsuke/github/GHUser.java +++ b/src/main/java/org/kohsuke/github/GHUser.java @@ -127,6 +127,23 @@ public class GHUser extends GHPerson { }; } + /** + * Lists Gists created by this user. + */ + public PagedIterable listGists() throws IOException { + return new PagedIterable() { + public PagedIterator iterator() { + return new PagedIterator(root.retrieve().asIterator(String.format("/users/%s/gists", login), GHGist[].class)) { + @Override + protected void wrapUp(GHGist[] page) { + for (GHGist c : page) + c.wrapUp(GHUser.this); + } + }; + } + }; + } + @Override public String toString() { return "User:"+login; diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 00f94bd04..1b990e036 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -329,6 +329,17 @@ public class GitHub { return Arrays.asList(events); } + /** + * Gets a sigle gist by ID. + */ + public GHGist getGist(String id) throws IOException { + return retrieve().to("/gists/"+id,GHGist.class).wrapUp(this); + } + + public GHGistBuilder createGist() { + return new GHGistBuilder(this); + } + /** * Parses the GitHub event object. * diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index e7e3e4674..10cb2bfb7 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -174,28 +174,7 @@ class Requester { while (true) {// loop while API rate limit is hit HttpURLConnection uc = setupConnection(root.getApiURL(tailApiUrl)); - if (!method.equals("GET")) { - uc.setDoOutput(true); - uc.setRequestProperty("Content-type", contentType); - - if (body == null) { - Map json = new HashMap(); - for (Entry e : args) { - json.put(e.key, e.value); - } - MAPPER.writeValue(uc.getOutputStream(), json); - } else { - try { - byte[] bytes = new byte[32768]; - int read = 0; - while ((read = body.read(bytes)) != -1) { - uc.getOutputStream().write(bytes, 0, read); - } - } finally { - body.close(); - } - } - } + buildRequest(uc); try { return parse(uc,type,instance); @@ -205,6 +184,48 @@ class Requester { } } + /** + * Makes a request and just obtains the HTTP status code. + */ + public int asHttpStatusCode(String tailApiUrl) throws IOException { + while (true) {// loop while API rate limit is hit + HttpURLConnection uc = setupConnection(root.getApiURL(tailApiUrl)); + + buildRequest(uc); + + try { + return uc.getResponseCode(); + } catch (IOException e) { + handleApiError(e,uc); + } + } + } + + private void buildRequest(HttpURLConnection uc) throws IOException { + if (!method.equals("GET")) { + uc.setDoOutput(true); + uc.setRequestProperty("Content-type", contentType); + + if (body == null) { + Map json = new HashMap(); + for (Entry e : args) { + json.put(e.key, e.value); + } + MAPPER.writeValue(uc.getOutputStream(), json); + } else { + try { + byte[] bytes = new byte[32768]; + int read = 0; + while ((read = body.read(bytes)) != -1) { + uc.getOutputStream().write(bytes, 0, read); + } + } finally { + body.close(); + } + } + } + } + /** * Loads pagenated resources. *