From f23afcd5aa13805ce7df5411f623143814562208 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Mon, 13 Apr 2015 18:30:43 -0700 Subject: [PATCH 001/390] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index b54c58bc47..48b93fc8da 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.67 + 1.68-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - github-api-1.67 + HEAD From cfc7005275c616c6b40710ab2ed30a726fe53368 Mon Sep 17 00:00:00 2001 From: Lee Skillen Date: Tue, 14 Apr 2015 14:45:47 +0100 Subject: [PATCH 002/390] Fix NullPointerException on RateLimiter when handling API errors. --- src/main/java/org/kohsuke/github/GitHub.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 744a6d36e9..d196481bc2 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -133,10 +133,11 @@ public class GitHub { } } + this.rateLimitHandler = rateLimitHandler; + if (login==null && encodedAuthorization!=null) login = getMyself().getLogin(); this.login = login; - this.rateLimitHandler = rateLimitHandler; } /** From 1e52dded141c8e58026cc692b2a31a17cf9038c8 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 15 Apr 2015 08:33:18 -0700 Subject: [PATCH 003/390] Added a helper method --- src/main/java/org/kohsuke/github/GHCommitPointer.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHCommitPointer.java b/src/main/java/org/kohsuke/github/GHCommitPointer.java index 7aaf4f01e1..b9716366b5 100644 --- a/src/main/java/org/kohsuke/github/GHCommitPointer.java +++ b/src/main/java/org/kohsuke/github/GHCommitPointer.java @@ -23,6 +23,8 @@ */ package org.kohsuke.github; +import java.io.IOException; + /** * Identifies a commit in {@link GHPullRequest}. * @@ -69,6 +71,13 @@ public String getLabel() { 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); From 63136f64b74c9492050ea0a4256d98a8f9e05966 Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Sun, 19 Apr 2015 17:20:54 -0700 Subject: [PATCH 004/390] Merge pull request #174 The merge was done manually because the original commit contains lots of whitespace only changes. --- .../org/kohsuke/github/GHPullRequest.java | 45 +++++- .../github/GHPullRequestCommitDetail.java | 144 ++++++++++-------- .../github/GHPullRequestFileDetail.java | 86 +++++++++++ .../github/GHPullRequestReviewComment.java | 105 +++++++++++++ 4 files changed, 313 insertions(+), 67 deletions(-) create mode 100644 src/main/java/org/kohsuke/github/GHPullRequestFileDetail.java create mode 100644 src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index 7c46a9c1c5..3d25a4f5a2 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -27,7 +27,6 @@ import java.net.URL; import java.util.Collection; import java.util.Date; -import java.util.Locale; /** * A pull request. @@ -197,6 +196,39 @@ private void populate() throws IOException { root.retrieve().to(url, this).wrapUp(owner); } + /** + * Retrieves all the commits associated to this pull request. + */ + public PagedIterable listFiles() { + return new PagedIterable() { + public PagedIterator iterator() { + return new PagedIterator(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 listReviewComments() throws IOException { + return new PagedIterable() { + public PagedIterator iterator() { + return new PagedIterator(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 PagedIterator iterator() { 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. * diff --git a/src/main/java/org/kohsuke/github/GHPullRequestCommitDetail.java b/src/main/java/org/kohsuke/github/GHPullRequestCommitDetail.java index 0ec7fff486..3568550904 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestCommitDetail.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestCommitDetail.java @@ -31,99 +31,111 @@ * Commit detail inside a {@link GHPullRequest}. * * @author Luca Milanesio + * @see GHPullRequest#listCommits() */ 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; + String sha; + String url; - public String getSha() { - return sha; - } + public String getSha() { + return sha; + } - public URL getUrl() { - return GitHub.parseURL(url); + 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; + 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; + } } - @WithBridgeMethods(value=Authorship.class,castRequired=true) - public GitUser getCommitter() { - return committer; - } + public static class CommitPointer { + String sha; + String url; + String html_url; - public String getMessage() { - return message; - } + public URL getUrl() { + return GitHub.parseURL(url); + } - public URL getUrl() { - return GitHub.parseURL(url); - } + public URL getHtml_url() { + return GitHub.parseURL(html_url); + } - public int getComment_count() { - return comment_count; + public String getSha() { + return sha; + } } - } - public static class CommitPointer { 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(url); + return GitHub.parseURL(html_url); } - public URL getHtml_url() { - return GitHub.parseURL(html_url); + public URL getCommentsUrl() { + return GitHub.parseURL(comments_url); } - public String getSha() { - return sha; + public CommitPointer[] getParents() { + return parents; } - } - - 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; - } } diff --git a/src/main/java/org/kohsuke/github/GHPullRequestFileDetail.java b/src/main/java/org/kohsuke/github/GHPullRequestFileDetail.java new file mode 100644 index 0000000000..1ee55d37cc --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHPullRequestFileDetail.java @@ -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; + } +} diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java b/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java new file mode 100644 index 0000000000..09863f78cf --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java @@ -0,0 +1,105 @@ +/* + * 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()+"/comments/"+id; + } + + /** + * Updates the comment. + */ + public void update(String body) throws IOException { + new Requester(owner.root).method("PATCH").with("body", body).to(getApiRoute(),this); + } + + /** + * Deletes this review comment. + */ + public void delete() throws IOException { + new Requester(owner.root).method("DELETE").to(getApiRoute()); + } +} From eeebb1b59fac231d6370d70abd3d7c638bfcd908 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sun, 19 Apr 2015 17:25:13 -0700 Subject: [PATCH 005/390] Added the 'sha' parameter. Fixes issue #176 --- .../java/org/kohsuke/github/GHPullRequest.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index 3d25a4f5a2..909110b727 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -266,7 +266,21 @@ public GHPullRequestReviewComment createReviewComment(String body, String sha, S * 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 { From 7b4d3a869b26b4ca4cbee1f41d721bda1cb2f401 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sun, 19 Apr 2015 17:40:35 -0700 Subject: [PATCH 006/390] [maven-release-plugin] prepare release github-api-1.68 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 48b93fc8da..992c9ef281 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.68-SNAPSHOT + 1.68 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - HEAD + github-api-1.68 From fd434292ad05e532561bdff2598be72e441ebff1 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sun, 19 Apr 2015 17:40:39 -0700 Subject: [PATCH 007/390] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 992c9ef281..e8f2ce2941 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.68 + 1.69-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - github-api-1.68 + HEAD From b976e0ef4ef70f26b8d75a1a847b251f8c895e62 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sun, 26 Apr 2015 10:52:43 -0700 Subject: [PATCH 008/390] Issue #180: don't write body if HTTP method is DELETE. --- src/main/java/org/kohsuke/github/Requester.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index 960940e7cf..253936c00a 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -287,7 +287,7 @@ public String getResponseHeader(String header) { * 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); @@ -296,7 +296,6 @@ private void buildRequest() throws IOException { for (Entry e : args) { json.put(e.key, e.value); } - MAPPER.writeValue(uc.getOutputStream(), json); } else { try { byte[] bytes = new byte[32768]; @@ -311,6 +310,12 @@ private void buildRequest() throws IOException { } } + private boolean isMethodWithBody() { + if (method.equals("GET")) return false; + if (method.equals("DELETE")) return false; + return true; + } + /** * Loads pagenated resources. * From 9b750bedef39660d21f8e06165a8ee56df5cc797 Mon Sep 17 00:00:00 2001 From: Marc Guenther Date: Wed, 29 Apr 2015 18:15:04 +0200 Subject: [PATCH 009/390] Fixes #183: added a method listForks() to GHRepository listForks() will list all forks of a repository. An optional sort argument is also supported. --- .../java/org/kohsuke/github/GHRepository.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index e4459e84d6..59d0dead97 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -505,6 +505,35 @@ public void delete() throws IOException { } } + /** + * Sort orders for listing forks + */ + public static enum Sort { NEWEST, OLDEST, STARGAZERS } + + /** + * Lists all the forks of this repository. + */ + public PagedIterable listForks() { + return listForks(null); + } + + /** + * Lists up all the forks of this repository, sorted by the given sort order. + */ + public PagedIterable listForks(final Sort sort) { + return new PagedIterable() { + public PagedIterator iterator() { + return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("forks" + ((sort == null)?"":("?sort="+sort.toString().toLowerCase(Locale.ENGLISH)))), GHRepository[].class)) { + @Override + protected void wrapUp(GHRepository[] page) { + for (GHRepository c : page) + c.wrap(root); + } + }; + } + }; + } + /** * Forks this repository as your repository. * From 626909addb2029c4f2baef34e3e4288d08e47bda Mon Sep 17 00:00:00 2001 From: yegorius Date: Fri, 1 May 2015 17:59:01 +0300 Subject: [PATCH 010/390] recognize previous_file field in GHCommit.File --- src/main/java/org/kohsuke/github/GHCommit.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHCommit.java b/src/main/java/org/kohsuke/github/GHCommit.java index fbb7c24fdd..ce56cddd6b 100644 --- a/src/main/java/org/kohsuke/github/GHCommit.java +++ b/src/main/java/org/kohsuke/github/GHCommit.java @@ -70,7 +70,8 @@ public static class Stats { 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 +102,19 @@ public String getStatus() { } /** - * Just the base name and the extension without any directory name. + * Full path in the repository. */ public String getFileName() { return filename; } + /** + * Previous path, in case file has moved. + */ + public String getPreviousFilename() { + return previous_filename; + } + /** * The actual change. */ From d77be9d3823b21b1ecc6920c0051cb2dc8c75234 Mon Sep 17 00:00:00 2001 From: Rob Schoening Date: Sat, 9 May 2015 01:01:04 -0700 Subject: [PATCH 011/390] fixed regression that caused POST operations to be sent as GET --- src/main/java/org/kohsuke/github/Requester.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index 253936c00a..a517782595 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -296,6 +296,7 @@ private void buildRequest() throws IOException { for (Entry e : args) { json.put(e.key, e.value); } + MAPPER.writeValue(uc.getOutputStream(), json); } else { try { byte[] bytes = new byte[32768]; From e4de09c55b516c41b2c7e596f23e23c4bf36a8ab Mon Sep 17 00:00:00 2001 From: Rob Schoening Date: Sat, 9 May 2015 01:05:04 -0700 Subject: [PATCH 012/390] allow default branch to be set --- src/main/java/org/kohsuke/github/GHRepository.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index e4459e84d6..5a7550ea2c 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -494,6 +494,12 @@ public void setHomepage(String value) throws IOException { edit("homepage",value); } + public void setMasterBranch(String value) throws IOException { + // This method might be more aptly named setDefaultBranch, + // but we'll use setMasterBranch for consistency with the existing getMasterBranch. + edit("default_branch", value); + } + /** * Deletes this repository. */ From f4b105b10f2a849a3752fa65d21f2c9a44af8986 Mon Sep 17 00:00:00 2001 From: Chris Hut Date: Tue, 12 May 2015 17:58:55 -0700 Subject: [PATCH 013/390] 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. --- src/main/java/org/kohsuke/github/GHEvent.java | 1 + src/main/java/org/kohsuke/github/GHHook.java | 18 +-- src/main/java/org/kohsuke/github/GHHooks.java | 130 ++++++++++++++++++ .../java/org/kohsuke/github/GHOrgHook.java | 27 ++++ .../org/kohsuke/github/GHOrganization.java | 40 +++++- .../java/org/kohsuke/github/GHRepoHook.java | 23 ++++ .../java/org/kohsuke/github/GHRepository.java | 66 ++++----- 7 files changed, 251 insertions(+), 54 deletions(-) create mode 100644 src/main/java/org/kohsuke/github/GHHooks.java create mode 100644 src/main/java/org/kohsuke/github/GHOrgHook.java create mode 100644 src/main/java/org/kohsuke/github/GHRepoHook.java diff --git a/src/main/java/org/kohsuke/github/GHEvent.java b/src/main/java/org/kohsuke/github/GHEvent.java index 13ef432f8f..425c304d7b 100644 --- a/src/main/java/org/kohsuke/github/GHEvent.java +++ b/src/main/java/org/kohsuke/github/GHEvent.java @@ -28,6 +28,7 @@ public enum GHEvent { PULL_REQUEST_REVIEW_COMMENT, PUSH, RELEASE, + REPOSITORY, // only valid for org hooks STATUS, TEAM_ADD, WATCH diff --git a/src/main/java/org/kohsuke/github/GHHook.java b/src/main/java/org/kohsuke/github/GHHook.java index ffe4837509..9d874351ad 100644 --- a/src/main/java/org/kohsuke/github/GHHook.java +++ b/src/main/java/org/kohsuke/github/GHHook.java @@ -11,22 +11,12 @@ /** * @author Kohsuke Kawaguchi */ -public class GHHook extends GHObject { - /** - * Repository that the hook belongs to. - */ - /*package*/ transient GHRepository repository; - +public abstract class GHHook extends GHObject { String name; List events; boolean active; Map config; - /*package*/ GHHook wrap(GHRepository owner) { - this.repository = owner; - return this; - } - public String getName() { return name; } @@ -50,7 +40,7 @@ public Map getConfig() { * 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(root()).method("DELETE").to(path()); } /** @@ -60,4 +50,8 @@ public void delete() throws IOException { public URL getHtmlUrl() { return null; } + + abstract GitHub root(); + + abstract String path(); } diff --git a/src/main/java/org/kohsuke/github/GHHooks.java b/src/main/java/org/kohsuke/github/GHHooks.java new file mode 100644 index 0000000000..1a6154aa6d --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHHooks.java @@ -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 getHooks() throws IOException { + List list = new ArrayList(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 config, Collection events, boolean active) throws IOException { + List ea = null; + if (events!=null) { + ea = new ArrayList(); + 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 collectionClass(); + + abstract Class 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 collectionClass() { + return GHRepoHook[].class; + } + + @Override + Class 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 collectionClass() { + return GHOrgHook[].class; + } + + @Override + Class 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); + } +} diff --git a/src/main/java/org/kohsuke/github/GHOrgHook.java b/src/main/java/org/kohsuke/github/GHOrgHook.java new file mode 100644 index 0000000000..94dc50f0bb --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHOrgHook.java @@ -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 root() { + return organization.root; + } + + @Override + String path() { + return String.format("/orgs/%s/hooks/%d", organization.getLogin(), id); + } +} diff --git a/src/main/java/org/kohsuke/github/GHOrganization.java b/src/main/java/org/kohsuke/github/GHOrganization.java index 0680ca39ca..4409dafaaa 100644 --- a/src/main/java/org/kohsuke/github/GHOrganization.java +++ b/src/main/java/org/kohsuke/github/GHOrganization.java @@ -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 GHRepository createRepository(String name, String description, String hom 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 { @@ -252,4 +255,39 @@ protected void wrapUp(GHRepository[] page) { } }; } + + /** + * Retrieves the currently configured hooks. + */ + public List 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 config, Collection events, boolean active) throws IOException { + return GHHooks.orgContext(this).createHook(name, config, events, active); + } + + public GHHook createWebHook(URL url, Collection events) throws IOException { + return createHook("web", Collections.singletonMap("url", url.toExternalForm()),events,true); + } + + public GHHook createWebHook(URL url) throws IOException { + return createWebHook(url, null); + } } diff --git a/src/main/java/org/kohsuke/github/GHRepoHook.java b/src/main/java/org/kohsuke/github/GHRepoHook.java new file mode 100644 index 0000000000..afcd9f222f --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHRepoHook.java @@ -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 root() { + return repository.root; + } + + @Override + String path() { + return String.format("/repos/%s/%s/hooks/%d", repository.getOwnerName(), repository.getName(), id); + } +} diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index e4459e84d6..99c6c80cd9 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -40,7 +40,7 @@ /** * A repository on GitHub. - * + * * @author Kohsuke Kawaguchi */ @SuppressWarnings({"UnusedDeclaration"}) @@ -57,14 +57,14 @@ public class GHRepository extends GHObject { private int watchers,forks,open_issues,size,network_count,subscribers_count; private String pushed_at; private Map milestones = new HashMap(); - + private String default_branch,language; private Map commits = new HashMap(); private GHRepoPermission permissions; private GHRepository source, parent; - + public GHDeploymentBuilder createDeployment(String ref) { return new GHDeploymentBuilder(this,ref); } @@ -164,7 +164,7 @@ public String getSshUrl() { 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 */ @@ -597,15 +597,11 @@ public GHPullRequest createPullRequest(String title, String head, String base, S * Retrieves the currently configured hooks. */ public List getHooks() throws IOException { - List list = new ArrayList(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); } /** @@ -649,7 +645,7 @@ public GHRef[] getRefs(String refType) throws IOException { } /** * Retrive a ref of the given type for the current GitHub repository. - * + * * @param refName * eg: heads/branch * @return refs matching the request type @@ -662,7 +658,7 @@ public GHRef getRef(String refName) throws IOException { } /** * 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 @@ -673,11 +669,11 @@ 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 @@ -774,7 +770,7 @@ public GHCommitStatus getLastCommitStatus(String sha1) throws IOException { * @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) @@ -784,7 +780,7 @@ public GHCommitStatus createCommitStatus(String sha1, GHCommitState state, Strin .with("context", context) .to(String.format("/repos/%s/%s/statuses/%s",owner.login,this.name,sha1),GHCommitStatus.class).wrapUp(root); } - + /** * @see #createCommitStatus(String, GHCommitState,String,String,String) */ @@ -858,10 +854,10 @@ protected void wrapUp(GHUser[] page) { } /** - * + * * 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 @@ -870,21 +866,9 @@ protected void wrapUp(GHUser[] page) { * Can be null. Types of events to hook into. */ public GHHook createHook(String name, Map config, Collection events, boolean active) throws IOException { - List ea = null; - if (events!=null) { - ea = new ArrayList(); - 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 events) throws IOException { return createHook("web",Collections.singletonMap("url",url.toExternalForm()),events,true); } @@ -909,8 +893,8 @@ private void verifyMine() throws IOException { /** * 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)} */ public Set getPostCommitHooks() { @@ -1098,19 +1082,19 @@ public GHMilestone createMilestone(String title, String description) throws IOEx 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) .with("title", title).with("key", key).method("POST").to(getApiTailUrl("keys"), GHDeployKey.class).wrap(this); - + } - + public List getDeployKeys() throws IOException{ List list = new ArrayList(Arrays.asList( root.retrieve().to(getApiTailUrl("keys"), GHDeployKey[].class))); for (GHDeployKey h : list) h.wrap(this); - return list; + return list; } /** @@ -1119,7 +1103,7 @@ public List getDeployKeys() throws IOException{ * @return * {@link GHRepository} that points to the root repository where this repository is forked * (indirectly or directly) from. Otherwise null. - * @see #getParent() + * @see #getParent() */ public GHRepository getSource() throws IOException { if (source == null) return null; @@ -1136,7 +1120,7 @@ public GHRepository getSource() throws IOException { * @return * {@link GHRepository} that points to the repository where this repository is forked * directly from. Otherwise null. - * @see #getSource() + * @see #getSource() */ public GHRepository getParent() throws IOException { if (parent == null) return null; @@ -1144,7 +1128,7 @@ public GHRepository getParent() throws IOException { parent = root.getRepository(parent.getFullName()); return parent; } - + /** * Subscribes to this repository to get notifications. */ From a5425a3c716e96b249b4c2410ca710e4caab5e0e Mon Sep 17 00:00:00 2001 From: Marc Guenther Date: Thu, 28 May 2015 22:18:02 +0200 Subject: [PATCH 014/390] improved javadoc for listForks() --- src/main/java/org/kohsuke/github/GHRepository.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 59d0dead97..505ab14711 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -321,6 +321,10 @@ public boolean isFork() { 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; } @@ -511,14 +515,15 @@ public void delete() throws IOException { public static enum Sort { NEWEST, OLDEST, STARGAZERS } /** - * Lists all the forks of this repository. + * Lists all the direct forks of this repository, sorted by {@link Sort#NEWEST Sort.NEWEST} */ public PagedIterable listForks() { return listForks(null); } /** - * Lists up all the forks of this repository, sorted by the given sort order. + * Lists all the direct forks of this repository, sorted by the given sort order. + * @param sort the sort order. If null, defaults to {@link Sort#NEWEST Sort.NEWEST}. */ public PagedIterable listForks(final Sort sort) { return new PagedIterable() { From 9d91549803dd2508b342b0909640859802fb3376 Mon Sep 17 00:00:00 2001 From: Koji Habu Date: Wed, 10 Jun 2015 15:43:57 -0700 Subject: [PATCH 015/390] added Page Build --- src/main/java/org/kohsuke/github/GHEvent.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/kohsuke/github/GHEvent.java b/src/main/java/org/kohsuke/github/GHEvent.java index 13ef432f8f..f6f0c8c0e7 100644 --- a/src/main/java/org/kohsuke/github/GHEvent.java +++ b/src/main/java/org/kohsuke/github/GHEvent.java @@ -23,6 +23,7 @@ public enum GHEvent { ISSUE_COMMENT, ISSUES, MEMBER, + PAGE_BUILD, PUBLIC, PULL_REQUEST, PULL_REQUEST_REVIEW_COMMENT, From ed76cdbddf4fc337fedec1f896b7e684e02beeaa Mon Sep 17 00:00:00 2001 From: MerkushevKirill Date: Thu, 11 Jun 2015 14:49:26 +0300 Subject: [PATCH 016/390] fix for GH Enterprise which does not have rate limit reset field Fixes regression from a4c1c8de24f7f1ab38b28e5e6f19cc46a5993d5d --- src/main/java/org/kohsuke/github/GitHub.java | 2 ++ .../java/org/kohsuke/github/GitHubTest.java | 30 ++++++++++++++----- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index d196481bc2..d3853380e8 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -45,6 +45,7 @@ import java.util.Map; import java.util.Set; import java.util.TimeZone; +import java.util.concurrent.TimeUnit; import org.apache.commons.codec.binary.Base64; @@ -248,6 +249,7 @@ public GHRateLimit getRateLimit() throws IOException { // see issue #78 GHRateLimit r = new GHRateLimit(); r.limit = r.remaining = 1000000; + r.reset = new Date(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(1)); return r; } } diff --git a/src/test/java/org/kohsuke/github/GitHubTest.java b/src/test/java/org/kohsuke/github/GitHubTest.java index 578bbc13f3..54ce6e35d7 100644 --- a/src/test/java/org/kohsuke/github/GitHubTest.java +++ b/src/test/java/org/kohsuke/github/GitHubTest.java @@ -1,34 +1,40 @@ 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 { Mapprops = new HashMap(); @@ -86,7 +92,7 @@ private void setupEnvironment(Map newenv) { e1.printStackTrace(); } } - + @Test public void testGitHubBuilderFromCustomEnvironment() throws IOException { Map props = new HashMap(); @@ -105,4 +111,12 @@ public void testGitHubBuilderFromCustomEnvironment() throws IOException { 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()); + } } From 861fd55d06e1ad4250d36f34a388747d5dcb833c Mon Sep 17 00:00:00 2001 From: MerkushevKirill Date: Mon, 15 Jun 2015 17:57:16 +0300 Subject: [PATCH 017/390] fix for unused json map when method with body, but body is null fixes regression from b976e0ef4ef70f26b8d75a1a847b251f8c895e62 --- src/main/java/org/kohsuke/github/Requester.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index 253936c00a..f852e3b10d 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -53,6 +53,7 @@ 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 @@ * @author Kohsuke Kawaguchi */ class Requester { + private static final List METHODS_WITHOUT_BODY = asList("GET", "DELETE"); + private final GitHub root; private final List args = new ArrayList(); private final Map headers = new LinkedHashMap(); @@ -296,6 +299,7 @@ private void buildRequest() throws IOException { for (Entry e : args) { json.put(e.key, e.value); } + MAPPER.writeValue(uc.getOutputStream(), json); } else { try { byte[] bytes = new byte[32768]; @@ -311,9 +315,7 @@ private void buildRequest() throws IOException { } private boolean isMethodWithBody() { - if (method.equals("GET")) return false; - if (method.equals("DELETE")) return false; - return true; + return !METHODS_WITHOUT_BODY.contains(method); } /** From 931ed7adac459e79c9b11843b5caad18753022e7 Mon Sep 17 00:00:00 2001 From: MerkushevKirill Date: Mon, 15 Jun 2015 18:14:58 +0300 Subject: [PATCH 018/390] don't ignore args when method without body in case of GET or DELETE request --- src/main/java/org/kohsuke/github/Requester.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index f852e3b10d..281426dd3e 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -211,7 +211,7 @@ public T to(String tailApiUrl, Class type, String method) throws IOExcept private T _to(String tailApiUrl, Class 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 ? '?' : '&'); From 492ff58aa827bc63bb9d70060dbcebd7cf013c1a Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Mon, 27 Apr 2015 15:39:37 +0200 Subject: [PATCH 019/390] Fix invalid URL for pull request comments update/delete --- .../github/GHPullRequestReviewComment.java | 2 +- .../org/kohsuke/github/PullRequestTest.java | 37 ++++++++++++++++++- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java b/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java index 09863f78cf..4cfe9de839 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java @@ -86,7 +86,7 @@ public URL getHtmlUrl() { } protected String getApiRoute() { - return "/repos/"+owner.getRepository().getFullName()+"/comments/"+id; + return "/repos/"+owner.getRepository().getFullName()+"/pulls/comments/"+id; } /** diff --git a/src/test/java/org/kohsuke/github/PullRequestTest.java b/src/test/java/org/kohsuke/github/PullRequestTest.java index c513860eae..d16c4988ba 100644 --- a/src/test/java/org/kohsuke/github/PullRequestTest.java +++ b/src/test/java/org/kohsuke/github/PullRequestTest.java @@ -5,6 +5,7 @@ import java.io.IOException; import java.util.Collection; +import java.util.List; /** * @author Kohsuke Kawaguchi @@ -18,7 +19,38 @@ public void createPullRequest() throws Exception { 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 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 void setLabels() throws Exception { 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(); From cce02aec3d5d767ceb8f921114aa523f961f5c0b Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Fri, 22 May 2015 09:50:52 +0200 Subject: [PATCH 020/390] Add delete and update for GHIssueComment --- src/main/java/org/kohsuke/github/GHIssue.java | 5 +++-- .../org/kohsuke/github/GHIssueComment.java | 19 +++++++++++++++++++ .../github/GHPullRequestReviewComment.java | 1 + 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHIssue.java b/src/main/java/org/kohsuke/github/GHIssue.java index 8c071a93f8..71394a6b0f 100644 --- a/src/main/java/org/kohsuke/github/GHIssue.java +++ b/src/main/java/org/kohsuke/github/GHIssue.java @@ -141,8 +141,9 @@ public URL getApiURL(){ /** * Updates the issue by adding a comment. */ - public void comment(String message) throws IOException { - new Requester(root).with("body",message).to(getIssuesApiRoute() + "/comments"); + 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 { diff --git a/src/main/java/org/kohsuke/github/GHIssueComment.java b/src/main/java/org/kohsuke/github/GHIssueComment.java index 732c508a2d..f36b110499 100644 --- a/src/main/java/org/kohsuke/github/GHIssueComment.java +++ b/src/main/java/org/kohsuke/github/GHIssueComment.java @@ -79,4 +79,23 @@ public GHUser getUser() throws IOException { 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(getCommentApiTail(), GHIssueComment.class); + this.body = body; + } + + /** + * Deletes this issue comment. + */ + public void delete() throws IOException { + new Requester(owner.root).method("DELETE").to(getCommentApiTail()); + } + + private String getCommentApiTail() { + return "/repos/"+owner.getRepository().getOwnerName()+"/"+owner.getRepository().getName()+"/issues/comments/" + id; + } } diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java b/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java index 09863f78cf..3051f4b700 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java @@ -94,6 +94,7 @@ protected String getApiRoute() { */ public void update(String body) throws IOException { new Requester(owner.root).method("PATCH").with("body", body).to(getApiRoute(),this); + this.body = body; } /** From b0d1eac477425d730e0919ed6aac2fb3d87852e5 Mon Sep 17 00:00:00 2001 From: Luca Milanesio Date: Fri, 26 Jun 2015 09:34:45 +0100 Subject: [PATCH 021/390] 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) --- .../java/org/kohsuke/github/GHMyself.java | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHMyself.java b/src/main/java/org/kohsuke/github/GHMyself.java index 7b588e88fa..b43ddc1126 100644 --- a/src/main/java/org/kohsuke/github/GHMyself.java +++ b/src/main/java/org/kohsuke/github/GHMyself.java @@ -17,6 +17,18 @@ * @author Kohsuke Kawaguchi */ public class GHMyself extends GHUser { + + /** + * Type of repositories returned during listing. + */ + public enum RepositoryType { + ALL, // All public and private repositories that current user has access or collaborates to + OWNER, // Public and private repositories owned by current user + PUBLIC, // Public repositories that current user has access or collaborates to + PRIVATE, // Private repositories that current user has access or collaborates to + MEMBER; // Public and private repositories that current user is a member + } + /** * @deprecated * Use {@link #getEmails2()} @@ -109,16 +121,31 @@ public PagedIterable listRepositories() { } /** - * 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 listRepositories(final int pageSize) { + return listRepositories(pageSize, RepositoryType.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 listRepositories(final int pageSize, final RepositoryType repoType) { return new PagedIterable() { public PagedIterator iterator() { - return new PagedIterator(root.retrieve().asIterator("/user/repos?per_page=" + pageSize, GHRepository[].class)) { + return new PagedIterator(root.retrieve().asIterator("/user/repos?per_page=" + pageSize + + "&type=" + repoType.name().toLowerCase(), GHRepository[].class)) { @Override protected void wrapUp(GHRepository[] page) { for (GHRepository c : page) From 90d1047fb29d80adf16fcc173b78e25632efcff9 Mon Sep 17 00:00:00 2001 From: MerkushevKirill Date: Sun, 5 Jul 2015 19:37:56 +0300 Subject: [PATCH 022/390] add ping event to GH events enum --- src/main/java/org/kohsuke/github/GHEvent.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHEvent.java b/src/main/java/org/kohsuke/github/GHEvent.java index 13ef432f8f..10b9881b66 100644 --- a/src/main/java/org/kohsuke/github/GHEvent.java +++ b/src/main/java/org/kohsuke/github/GHEvent.java @@ -30,5 +30,6 @@ public enum GHEvent { RELEASE, STATUS, TEAM_ADD, - WATCH + WATCH, + PING } From 01b8b1034411f6b9e44c5e49849f6ae0cedc9efc Mon Sep 17 00:00:00 2001 From: Stephen Connolly Date: Mon, 6 Jul 2015 11:07:05 +0100 Subject: [PATCH 023/390] Fix NPE found when resolving issues from search api --- src/main/java/org/kohsuke/github/GHEventPayload.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHEventPayload.java b/src/main/java/org/kohsuke/github/GHEventPayload.java index cd248c80ec..e60fa40193 100644 --- a/src/main/java/org/kohsuke/github/GHEventPayload.java +++ b/src/main/java/org/kohsuke/github/GHEventPayload.java @@ -104,8 +104,12 @@ public void setRepository(GHRepository repository) { @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); } } From ec5392708fb8766979eabadea830a4b4ab5fac2f Mon Sep 17 00:00:00 2001 From: torodev Date: Tue, 14 Jul 2015 09:47:04 +0800 Subject: [PATCH 024/390] Specified the GET Previously doesn't specify the HTTP method to perform --- src/main/java/org/kohsuke/github/GHRepository.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index e4459e84d6..84c58641b0 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -1162,7 +1162,7 @@ public GHSubscription subscribe(boolean subscribed, boolean ignored) throws IOEx */ 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; } From 5a418dcce6b11fcb4f5a3a92ad728654c809bbc4 Mon Sep 17 00:00:00 2001 From: Oleg Nenashev Date: Thu, 16 Jul 2015 16:56:09 +0300 Subject: [PATCH 025/390] Enable FindBugs --- pom.xml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/pom.xml b/pom.xml index e252104a93..2ff028a352 100644 --- a/pom.xml +++ b/pom.xml @@ -44,6 +44,25 @@ + + org.codehaus.mojo + findbugs-maven-plugin + 3.0.1 + + true + true + false + + + + run-findbugs + verify + + check + + + + @@ -108,6 +127,12 @@ mockito-all 1.9.5 + + com.google.code.findbugs + annotations + 3.0.0 + provided + From a83aad22cac75f0789c0fe01d466a9e08c76bc06 Mon Sep 17 00:00:00 2001 From: Marc Guenther Date: Fri, 17 Jul 2015 09:33:48 +0200 Subject: [PATCH 026/390] renamed Sort enum, some cleanup, better javadoc --- .../java/org/kohsuke/github/GHRepository.java | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 505ab14711..f9337a5ef7 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -37,6 +37,7 @@ import java.util.*; import static java.util.Arrays.asList; +import static org.apache.commons.lang.ObjectUtils.defaultIfNull; /** * A repository on GitHub. @@ -512,10 +513,11 @@ public void delete() throws IOException { /** * Sort orders for listing forks */ - public static enum Sort { NEWEST, OLDEST, STARGAZERS } + public static enum ForkSort { NEWEST, OLDEST, STARGAZERS } /** - * Lists all the direct forks of this repository, sorted by {@link Sort#NEWEST Sort.NEWEST} + * Lists all the direct forks of this repository, sorted by + * github api default, currently {@link ForkSort#NEWEST ForkSort.NEWEST}. */ public PagedIterable listForks() { return listForks(null); @@ -523,16 +525,22 @@ public PagedIterable listForks() { /** * Lists all the direct forks of this repository, sorted by the given sort order. - * @param sort the sort order. If null, defaults to {@link Sort#NEWEST Sort.NEWEST}. + * @param sort the sort order. If null, defaults to github api default, + * currently {@link ForkSort#NEWEST ForkSort.NEWEST}. */ - public PagedIterable listForks(final Sort sort) { + public PagedIterable listForks(final ForkSort sort) { return new PagedIterable() { public PagedIterator iterator() { - return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("forks" + ((sort == null)?"":("?sort="+sort.toString().toLowerCase(Locale.ENGLISH)))), GHRepository[].class)) { + String sortParam = ""; + if (sort != null) { + sortParam = "?sort=" + sort.toString().toLowerCase(Locale.ENGLISH); + } + return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("forks" + sortParam), GHRepository[].class)) { @Override protected void wrapUp(GHRepository[] page) { - for (GHRepository c : page) + for (GHRepository c : page) { c.wrap(root); + } } }; } From b0c54ef0f10cbaea45fafe830832f13cf1b69f24 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 17 Jul 2015 13:27:20 +0300 Subject: [PATCH 027/390] Restored backward compatibility with the former signature --- src/main/java/org/kohsuke/github/GHIssue.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHIssue.java b/src/main/java/org/kohsuke/github/GHIssue.java index 71394a6b0f..e7864087dd 100644 --- a/src/main/java/org/kohsuke/github/GHIssue.java +++ b/src/main/java/org/kohsuke/github/GHIssue.java @@ -24,6 +24,8 @@ package org.kohsuke.github; +import com.infradna.tool.bridge_method_injector.WithBridgeMethods; + import java.io.IOException; import java.net.URL; import java.util.Collection; @@ -140,7 +142,11 @@ public URL getApiURL(){ /** * Updates the issue by adding a comment. + * + * @return + * Newly posted comment. */ + @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); @@ -177,7 +183,7 @@ public void setBody(String body) throws IOException { } public void assignTo(GHUser user) throws IOException { - editIssue("assignee",user.getLogin()); + editIssue("assignee", user.getLogin()); } public void setLabels(String... labels) throws IOException { From 025806f0fd56b423f6f94d887e9858da6348b5ba Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 17 Jul 2015 13:29:07 +0300 Subject: [PATCH 028/390] Consistent name with other classes --- src/main/java/org/kohsuke/github/GHIssueComment.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHIssueComment.java b/src/main/java/org/kohsuke/github/GHIssueComment.java index f36b110499..3179fa93a6 100644 --- a/src/main/java/org/kohsuke/github/GHIssueComment.java +++ b/src/main/java/org/kohsuke/github/GHIssueComment.java @@ -25,7 +25,6 @@ import java.io.IOException; import java.net.URL; -import java.util.Date; /** * Comment to the issue @@ -84,7 +83,7 @@ public URL getHtmlUrl() { * Updates the body of the issue comment. */ public void update(String body) throws IOException { - new Requester(owner.root).with("body", body).method("PATCH").to(getCommentApiTail(), GHIssueComment.class); + new Requester(owner.root).with("body", body).method("PATCH").to(getApiRoute(), GHIssueComment.class); this.body = body; } @@ -92,10 +91,10 @@ public void update(String body) throws IOException { * Deletes this issue comment. */ public void delete() throws IOException { - new Requester(owner.root).method("DELETE").to(getCommentApiTail()); + new Requester(owner.root).method("DELETE").to(getApiRoute()); } - private String getCommentApiTail() { + private String getApiRoute() { return "/repos/"+owner.getRepository().getOwnerName()+"/"+owner.getRepository().getName()+"/issues/comments/" + id; } } From 23c56ff887c2583c3c3c49d6cc9fd2442c775fe7 Mon Sep 17 00:00:00 2001 From: Marc Guenther Date: Fri, 17 Jul 2015 12:30:49 +0200 Subject: [PATCH 029/390] remove unused import --- src/main/java/org/kohsuke/github/GHRepository.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index f9337a5ef7..502e0fb6c6 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -37,7 +37,6 @@ import java.util.*; import static java.util.Arrays.asList; -import static org.apache.commons.lang.ObjectUtils.defaultIfNull; /** * A repository on GitHub. From eb9551d81b896262945769ca469a7ecba482834e Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 17 Jul 2015 13:42:20 +0300 Subject: [PATCH 030/390] Renamed getMasterBranch to getDefaultBranch The new set method can be simply renamed without the backward compatibility version since it's new --- src/main/java/org/kohsuke/github/GHRepository.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 5a7550ea2c..f898440220 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -364,6 +364,14 @@ public Date getPushedAt() { * @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; } @@ -494,9 +502,7 @@ public void setHomepage(String value) throws IOException { edit("homepage",value); } - public void setMasterBranch(String value) throws IOException { - // This method might be more aptly named setDefaultBranch, - // but we'll use setMasterBranch for consistency with the existing getMasterBranch. + public void setDefaultBranch(String value) throws IOException { edit("default_branch", value); } From dd21bcb34ce1994b96a388f36fe564edd2d03c18 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 17 Jul 2015 13:51:31 +0300 Subject: [PATCH 031/390] I think this is a better name --- src/main/java/org/kohsuke/github/GHMyself.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHMyself.java b/src/main/java/org/kohsuke/github/GHMyself.java index b43ddc1126..b0eee7b8e3 100644 --- a/src/main/java/org/kohsuke/github/GHMyself.java +++ b/src/main/java/org/kohsuke/github/GHMyself.java @@ -5,7 +5,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -21,7 +20,7 @@ public class GHMyself extends GHUser { /** * Type of repositories returned during listing. */ - public enum RepositoryType { + public enum RepositoryListFilter { ALL, // All public and private repositories that current user has access or collaborates to OWNER, // Public and private repositories owned by current user PUBLIC, // Public repositories that current user has access or collaborates to @@ -132,7 +131,7 @@ public PagedIterable listRepositories() { * Unlike {@link #getRepositories()}, this does not wait until all the repositories are returned. */ public PagedIterable listRepositories(final int pageSize) { - return listRepositories(pageSize, RepositoryType.ALL); + return listRepositories(pageSize, RepositoryListFilter.ALL); } /** @@ -141,7 +140,7 @@ public PagedIterable listRepositories(final int pageSize) { * @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 listRepositories(final int pageSize, final RepositoryType repoType) { + public PagedIterable listRepositories(final int pageSize, final RepositoryListFilter repoType) { return new PagedIterable() { public PagedIterator iterator() { return new PagedIterator(root.retrieve().asIterator("/user/repos?per_page=" + pageSize + From 90daf8087e8648cd403e3e26b5f01878701fc874 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 17 Jul 2015 13:52:16 +0300 Subject: [PATCH 032/390] Turning this into javadoc so that users can see them in IDE. --- .../java/org/kohsuke/github/GHMyself.java | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHMyself.java b/src/main/java/org/kohsuke/github/GHMyself.java index b0eee7b8e3..2041336367 100644 --- a/src/main/java/org/kohsuke/github/GHMyself.java +++ b/src/main/java/org/kohsuke/github/GHMyself.java @@ -21,11 +21,26 @@ public class GHMyself extends GHUser { * Type of repositories returned during listing. */ public enum RepositoryListFilter { - ALL, // All public and private repositories that current user has access or collaborates to - OWNER, // Public and private repositories owned by current user - PUBLIC, // Public repositories that current user has access or collaborates to - PRIVATE, // Private repositories that current user has access or collaborates to - MEMBER; // Public and private repositories that current user is a member + /** + * 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; } /** From e239ef50bac10948d897f253bf3e56a8b8df2131 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 17 Jul 2015 14:06:35 +0300 Subject: [PATCH 033/390] Consistent name with other classes --- src/main/java/org/kohsuke/github/GHHook.java | 6 +++--- src/main/java/org/kohsuke/github/GHOrgHook.java | 4 ++-- src/main/java/org/kohsuke/github/GHRepoHook.java | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHHook.java b/src/main/java/org/kohsuke/github/GHHook.java index 9d874351ad..ce8c8a4dfd 100644 --- a/src/main/java/org/kohsuke/github/GHHook.java +++ b/src/main/java/org/kohsuke/github/GHHook.java @@ -40,7 +40,7 @@ public Map getConfig() { * Deletes this hook. */ public void delete() throws IOException { - new Requester(root()).method("DELETE").to(path()); + new Requester(getRoot()).method("DELETE").to(getApiRoute()); } /** @@ -51,7 +51,7 @@ public URL getHtmlUrl() { return null; } - abstract GitHub root(); + abstract GitHub getRoot(); - abstract String path(); + abstract String getApiRoute(); } diff --git a/src/main/java/org/kohsuke/github/GHOrgHook.java b/src/main/java/org/kohsuke/github/GHOrgHook.java index 94dc50f0bb..58404019bf 100644 --- a/src/main/java/org/kohsuke/github/GHOrgHook.java +++ b/src/main/java/org/kohsuke/github/GHOrgHook.java @@ -16,12 +16,12 @@ class GHOrgHook extends GHHook { } @Override - GitHub root() { + GitHub getRoot() { return organization.root; } @Override - String path() { + String getApiRoute() { return String.format("/orgs/%s/hooks/%d", organization.getLogin(), id); } } diff --git a/src/main/java/org/kohsuke/github/GHRepoHook.java b/src/main/java/org/kohsuke/github/GHRepoHook.java index afcd9f222f..948438eb96 100644 --- a/src/main/java/org/kohsuke/github/GHRepoHook.java +++ b/src/main/java/org/kohsuke/github/GHRepoHook.java @@ -12,12 +12,12 @@ class GHRepoHook extends GHHook { } @Override - GitHub root() { + GitHub getRoot() { return repository.root; } @Override - String path() { + String getApiRoute() { return String.format("/repos/%s/%s/hooks/%d", repository.getOwnerName(), repository.getName(), id); } } From ebc97f42ad40756b4db1dcd81aeeb758bb319e02 Mon Sep 17 00:00:00 2001 From: Oleg Nenashev Date: Fri, 17 Jul 2015 14:21:46 +0300 Subject: [PATCH 034/390] Fix potential NPE in the code --- src/main/java/org/kohsuke/github/GHBranch.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHBranch.java b/src/main/java/org/kohsuke/github/GHBranch.java index 1c68bfa758..9c3d331adc 100644 --- a/src/main/java/org/kohsuke/github/GHBranch.java +++ b/src/main/java/org/kohsuke/github/GHBranch.java @@ -40,7 +40,8 @@ public String getSHA1() { @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) { From 5f2c84a913ae5ca2bf0661e8bb59fa3661378e56 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 17 Jul 2015 14:31:16 +0300 Subject: [PATCH 035/390] 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. --- src/test/java/org/kohsuke/github/AppTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/org/kohsuke/github/AppTest.java b/src/test/java/org/kohsuke/github/AppTest.java index 5cdb17e987..d2b68e112c 100755 --- a/src/test/java/org/kohsuke/github/AppTest.java +++ b/src/test/java/org/kohsuke/github/AppTest.java @@ -351,7 +351,7 @@ public void testQueryCommits() throws Exception { sha1.add(c.getSHA1()); } assertEquals("1cccddb22e305397151b2b7b87b4b47d74ca337b",sha1.get(0)); - assertEquals(29,sha1.size()); + assertEquals(29, sha1.size()); } @Test @@ -618,7 +618,7 @@ public void directoryListing() throws IOException { @Test public void testAddDeployKey() throws IOException { - GHRepository myRepository = Iterables.get(gitHub.getMyself().getRepositories().values(),0); + 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,7 +636,7 @@ public boolean apply(GHDeployKey deployKey) { @Test public void testCommitStatusContext() throws IOException { - GHRepository myRepository = Iterables.get(gitHub.getMyself().getRepositories().values(), 0); + 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()); From f8408bd29f4cde06613e2d3077b1d45be0f9f2ff Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 17 Jul 2015 15:06:39 +0300 Subject: [PATCH 036/390] 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 --- src/test/java/org/kohsuke/github/PullRequestTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/kohsuke/github/PullRequestTest.java b/src/test/java/org/kohsuke/github/PullRequestTest.java index d16c4988ba..9fc55f7519 100644 --- a/src/test/java/org/kohsuke/github/PullRequestTest.java +++ b/src/test/java/org/kohsuke/github/PullRequestTest.java @@ -82,7 +82,7 @@ public void testGetUser() throws IOException { PagedIterable ghPullRequests = getRepository().listPullRequests(GHIssueState.OPEN); for (GHPullRequest pr : ghPullRequests) { assertNotNull(pr.getUser().root); - assertFalse(pr.getMergeable()); + pr.getMergeable(); assertNotNull(pr.getUser().root); } } From 505bb8f06d97f3f9203796c4a000d887e8c87616 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 17 Jul 2015 05:09:25 -0700 Subject: [PATCH 037/390] [maven-release-plugin] prepare release github-api-1.69 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 21fb790eb6..3c04540ce0 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.69-SNAPSHOT + 1.69 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - HEAD + github-api-1.69 From 2d45ac51efb4ad5f9121b328825e27067b7bad3c Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 17 Jul 2015 05:09:28 -0700 Subject: [PATCH 038/390] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 3c04540ce0..50462e77cc 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.69 + 1.70-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - github-api-1.69 + HEAD From 79c5b2edd5f918a26908ab5060b5b869ef0cc30c Mon Sep 17 00:00:00 2001 From: Oleg Nenashev Date: Mon, 20 Jul 2015 12:28:41 +0300 Subject: [PATCH 039/390] FindBugs: Fix over 100 issues and enforce FindBugs --- pom.xml | 6 ++- .../java/org/kohsuke/github/DeleteToken.java | 4 ++ .../org/kohsuke/github/GHAuthorization.java | 6 ++- .../java/org/kohsuke/github/GHBranch.java | 11 +++++- .../java/org/kohsuke/github/GHCommit.java | 19 +++++++++- .../org/kohsuke/github/GHCommitComment.java | 11 +++++- .../java/org/kohsuke/github/GHCompare.java | 16 +++++++- .../java/org/kohsuke/github/GHContent.java | 6 +-- .../kohsuke/github/GHDeploymentStatus.java | 4 +- .../github/GHDeploymentStatusBuilder.java | 3 +- src/main/java/org/kohsuke/github/GHEmail.java | 4 ++ .../java/org/kohsuke/github/GHEventInfo.java | 12 ++++++ .../org/kohsuke/github/GHEventPayload.java | 6 +++ src/main/java/org/kohsuke/github/GHHook.java | 3 ++ src/main/java/org/kohsuke/github/GHIssue.java | 3 ++ src/main/java/org/kohsuke/github/GHKey.java | 6 +++ .../java/org/kohsuke/github/GHMyself.java | 3 +- .../kohsuke/github/GHNotificationStream.java | 5 ++- .../java/org/kohsuke/github/GHObject.java | 15 ++------ .../org/kohsuke/github/GHOrganization.java | 2 +- .../java/org/kohsuke/github/GHPersonSet.java | 2 + .../github/GHPullRequestCommitDetail.java | 10 ++++- .../java/org/kohsuke/github/GHRateLimit.java | 3 ++ src/main/java/org/kohsuke/github/GHRef.java | 4 +- .../java/org/kohsuke/github/GHRelease.java | 11 ++++-- .../java/org/kohsuke/github/GHRepository.java | 37 +++++++++++++++++-- src/main/java/org/kohsuke/github/GHTag.java | 4 ++ .../java/org/kohsuke/github/GHThread.java | 7 ++++ src/main/java/org/kohsuke/github/GitHub.java | 9 ++++- src/main/java/org/kohsuke/github/GitUser.java | 3 ++ .../kohsuke/github/PagedSearchIterable.java | 3 ++ .../java/org/kohsuke/github/Requester.java | 20 ++++------ .../java/org/kohsuke/github/SearchResult.java | 6 +++ 33 files changed, 210 insertions(+), 54 deletions(-) diff --git a/pom.xml b/pom.xml index 21fb790eb6..9d55c08537 100644 --- a/pom.xml +++ b/pom.xml @@ -28,6 +28,8 @@ UTF-8 + 3.0.1 + true @@ -47,11 +49,11 @@ org.codehaus.mojo findbugs-maven-plugin - 3.0.1 + ${findbugs-maven-plugin.version} true true - false + ${findbugs-maven-plugin.failOnError} diff --git a/src/main/java/org/kohsuke/github/DeleteToken.java b/src/main/java/org/kohsuke/github/DeleteToken.java index eb61011920..d9d4724eb9 100644 --- a/src/main/java/org/kohsuke/github/DeleteToken.java +++ b/src/main/java/org/kohsuke/github/DeleteToken.java @@ -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; } diff --git a/src/main/java/org/kohsuke/github/GHAuthorization.java b/src/main/java/org/kohsuke/github/GHAuthorization.java index f990cbefb3..b8b7aff19a 100644 --- a/src/main/java/org/kohsuke/github/GHAuthorization.java +++ b/src/main/java/org/kohsuke/github/GHAuthorization.java @@ -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; @@ -59,6 +60,8 @@ 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); } @@ -84,7 +87,8 @@ public URL getNoteUrl() { return this; } - + @SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD"}, + justification = "JSON API") private static class App { private String url; private String name; diff --git a/src/main/java/org/kohsuke/github/GHBranch.java b/src/main/java/org/kohsuke/github/GHBranch.java index 9c3d331adc..272c643f47 100644 --- a/src/main/java/org/kohsuke/github/GHBranch.java +++ b/src/main/java/org/kohsuke/github/GHBranch.java @@ -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,7 +44,7 @@ public String getName() { public String getSHA1() { return commit.sha; } - + @Override public String toString() { final String url = owner != null ? owner.getUrl().toString() : "unknown"; diff --git a/src/main/java/org/kohsuke/github/GHCommit.java b/src/main/java/org/kohsuke/github/GHCommit.java index ce56cddd6b..b45683f2d2 100644 --- a/src/main/java/org/kohsuke/github/GHCommit.java +++ b/src/main/java/org/kohsuke/github/GHCommit.java @@ -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 @@ * @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; @@ -67,6 +72,8 @@ public static class Stats { /** * 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; @@ -104,6 +111,8 @@ public String getStatus() { /** * 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; } @@ -147,13 +156,19 @@ public String getSha() { } 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; diff --git a/src/main/java/org/kohsuke/github/GHCommitComment.java b/src/main/java/org/kohsuke/github/GHCommitComment.java index 7deebbc6ad..7020f9b98f 100644 --- a/src/main/java/org/kohsuke/github/GHCommitComment.java +++ b/src/main/java/org/kohsuke/github/GHCommitComment.java @@ -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 @@ * @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 GHCommit getCommit() throws IOException { * 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; diff --git a/src/main/java/org/kohsuke/github/GHCompare.java b/src/main/java/org/kohsuke/github/GHCompare.java index 2c2bc5ba72..c9c882ba4e 100644 --- a/src/main/java/org/kohsuke/github/GHCompare.java +++ b/src/main/java/org/kohsuke/github/GHCompare.java @@ -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,12 +67,20 @@ public Commit getMergeBaseCommit() { 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) { @@ -87,6 +97,8 @@ public GHCompare wrap(GHRepository owner) { * 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; diff --git a/src/main/java/org/kohsuke/github/GHContent.java b/src/main/java/org/kohsuke/github/GHContent.java index 8ab48d2fdd..bc96af5ddc 100644 --- a/src/main/java/org/kohsuke/github/GHContent.java +++ b/src/main/java/org/kohsuke/github/GHContent.java @@ -76,7 +76,7 @@ public String getPath() { * Use {@link #read()} */ public String getContent() throws IOException { - return new String(DatatypeConverter.parseBase64Binary(getEncodedContent())); + return new String(DatatypeConverter.parseBase64Binary(getEncodedContent()), getEncoding()); } /** @@ -162,11 +162,11 @@ protected void wrapUp(GHContent[] page) { } public GHContentUpdateResponse update(String newContent, String commitMessage) throws IOException { - return update(newContent.getBytes(), commitMessage, null); + return update(newContent.getBytes(getEncoding()), commitMessage, null); } public GHContentUpdateResponse update(String newContent, String commitMessage, String branch) throws IOException { - return update(newContent.getBytes(), commitMessage, branch); + return update(newContent.getBytes(getEncoding()), commitMessage, branch); } public GHContentUpdateResponse update(byte[] newContentBytes, String commitMessage) throws IOException { diff --git a/src/main/java/org/kohsuke/github/GHDeploymentStatus.java b/src/main/java/org/kohsuke/github/GHDeploymentStatus.java index c8679c1343..a058b8a447 100644 --- a/src/main/java/org/kohsuke/github/GHDeploymentStatus.java +++ b/src/main/java/org/kohsuke/github/GHDeploymentStatus.java @@ -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,8 +29,9 @@ public URL getDeploymentUrl() { public URL getRepositoryUrl() { return GitHub.parseURL(repository_url); } + public GHDeploymentState getState() { - return GHDeploymentState.valueOf(state.toUpperCase()); + return GHDeploymentState.valueOf(state.toUpperCase(Locale.ENGLISH)); } /** diff --git a/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java b/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java index 4310153800..b1ecf8918c 100644 --- a/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java +++ b/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java @@ -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 GHDeploymentStatusBuilder(GHRepository repo, int deploymentId, GHDeployme 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) { diff --git a/src/main/java/org/kohsuke/github/GHEmail.java b/src/main/java/org/kohsuke/github/GHEmail.java index 5f230c5945..9eeac04336 100644 --- a/src/main/java/org/kohsuke/github/GHEmail.java +++ b/src/main/java/org/kohsuke/github/GHEmail.java @@ -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; diff --git a/src/main/java/org/kohsuke/github/GHEventInfo.java b/src/main/java/org/kohsuke/github/GHEventInfo.java index 09db42aa0f..9772cba16e 100644 --- a/src/main/java/org/kohsuke/github/GHEventInfo.java +++ b/src/main/java/org/kohsuke/github/GHEventInfo.java @@ -4,12 +4,14 @@ 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 Date getCreatedAt() { /** * 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 String getActorLogin() throws IOException { 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()); } diff --git a/src/main/java/org/kohsuke/github/GHEventPayload.java b/src/main/java/org/kohsuke/github/GHEventPayload.java index e60fa40193..08b112880d 100644 --- a/src/main/java/org/kohsuke/github/GHEventPayload.java +++ b/src/main/java/org/kohsuke/github/GHEventPayload.java @@ -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 authoritative source */ + @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 @@ void wrapUp(GitHub root) { * * @see authoritative source */ + @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; } diff --git a/src/main/java/org/kohsuke/github/GHHook.java b/src/main/java/org/kohsuke/github/GHHook.java index ce8c8a4dfd..7d63f9d950 100644 --- a/src/main/java/org/kohsuke/github/GHHook.java +++ b/src/main/java/org/kohsuke/github/GHHook.java @@ -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.Collections; @@ -11,6 +12,8 @@ /** * @author Kohsuke Kawaguchi */ +@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 events; diff --git a/src/main/java/org/kohsuke/github/GHIssue.java b/src/main/java/org/kohsuke/github/GHIssue.java index e7864087dd..d45e49b935 100644 --- a/src/main/java/org/kohsuke/github/GHIssue.java +++ b/src/main/java/org/kohsuke/github/GHIssue.java @@ -25,6 +25,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; @@ -269,6 +270,8 @@ public GHMilestone getMilestone() { return milestone; } + @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; diff --git a/src/main/java/org/kohsuke/github/GHKey.java b/src/main/java/org/kohsuke/github/GHKey.java index 91632cf175..63ab7b3ff9 100644 --- a/src/main/java/org/kohsuke/github/GHKey.java +++ b/src/main/java/org/kohsuke/github/GHKey.java @@ -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 @@ * * @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 String getUrl() { return url; } + public GitHub getRoot() { + return root; + } + public boolean isVerified() { return verified; } diff --git a/src/main/java/org/kohsuke/github/GHMyself.java b/src/main/java/org/kohsuke/github/GHMyself.java index 2041336367..74ba96189d 100644 --- a/src/main/java/org/kohsuke/github/GHMyself.java +++ b/src/main/java/org/kohsuke/github/GHMyself.java @@ -6,6 +6,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.TreeMap; @@ -159,7 +160,7 @@ public PagedIterable listRepositories(final int pageSize, final Re return new PagedIterable() { public PagedIterator iterator() { return new PagedIterator(root.retrieve().asIterator("/user/repos?per_page=" + pageSize + - "&type=" + repoType.name().toLowerCase(), GHRepository[].class)) { + "&type=" + repoType.name().toLowerCase(Locale.ENGLISH), GHRepository[].class)) { @Override protected void wrapUp(GHRepository[] page) { for (GHRepository c : page) diff --git a/src/main/java/org/kohsuke/github/GHNotificationStream.java b/src/main/java/org/kohsuke/github/GHNotificationStream.java index 5ea6fb69cb..b8f8d7c296 100644 --- a/src/main/java/org/kohsuke/github/GHNotificationStream.java +++ b/src/main/java/org/kohsuke/github/GHNotificationStream.java @@ -152,7 +152,7 @@ GHThread fetch() { 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 @@ GHThread fetch() { 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() { diff --git a/src/main/java/org/kohsuke/github/GHObject.java b/src/main/java/org/kohsuke/github/GHObject.java index 914f1280d3..50aa0a6a86 100644 --- a/src/main/java/org/kohsuke/github/GHObject.java +++ b/src/main/java/org/kohsuke/github/GHObject.java @@ -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 @@ /** * 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 Date getCreatedAt() throws IOException { return GitHub.parseDate(created_at); } - private Object createdAtStr(Date id, Class type) { - return created_at; - } - /** * API URL of this object. */ @@ -58,12 +57,4 @@ public Date getUpdatedAt() throws IOException { 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(); - } } diff --git a/src/main/java/org/kohsuke/github/GHOrganization.java b/src/main/java/org/kohsuke/github/GHOrganization.java index 4409dafaaa..b39cc6b98b 100644 --- a/src/main/java/org/kohsuke/github/GHOrganization.java +++ b/src/main/java/org/kohsuke/github/GHOrganization.java @@ -175,7 +175,7 @@ public enum Permission { ADMIN, PUSH, PULL } * Creates a new team and assigns the repositories. */ public GHTeam createTeam(String name, Permission p, Collection 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 repo_names = new ArrayList(); for (GHRepository r : repositories) { repo_names.add(r.getName()); diff --git a/src/main/java/org/kohsuke/github/GHPersonSet.java b/src/main/java/org/kohsuke/github/GHPersonSet.java index 1c1d43dccb..eb35b1bf7a 100644 --- a/src/main/java/org/kohsuke/github/GHPersonSet.java +++ b/src/main/java/org/kohsuke/github/GHPersonSet.java @@ -10,6 +10,8 @@ * @author Kohsuke Kawaguchi */ public class GHPersonSet extends HashSet { + private static final long serialVersionUID = 1L; + public GHPersonSet() { } diff --git a/src/main/java/org/kohsuke/github/GHPullRequestCommitDetail.java b/src/main/java/org/kohsuke/github/GHPullRequestCommitDetail.java index 3568550904..d4b48da538 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestCommitDetail.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestCommitDetail.java @@ -24,8 +24,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; /** * Commit detail inside a {@link GHPullRequest}. @@ -33,6 +35,8 @@ * @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; @@ -88,6 +92,10 @@ public URL getUrl() { public int getComment_count() { return comment_count; } + + public Tree getTree() { + return tree; + } } public static class CommitPointer { @@ -136,6 +144,6 @@ public URL getCommentsUrl() { } public CommitPointer[] getParents() { - return parents; + return Arrays.copyOf(parents, parents.length); } } diff --git a/src/main/java/org/kohsuke/github/GHRateLimit.java b/src/main/java/org/kohsuke/github/GHRateLimit.java index 301bd7993d..b9b900d785 100644 --- a/src/main/java/org/kohsuke/github/GHRateLimit.java +++ b/src/main/java/org/kohsuke/github/GHRateLimit.java @@ -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); } diff --git a/src/main/java/org/kohsuke/github/GHRef.java b/src/main/java/org/kohsuke/github/GHRef.java index f052cdf903..8212dc2c3b 100644 --- a/src/main/java/org/kohsuke/github/GHRef.java +++ b/src/main/java/org/kohsuke/github/GHRef.java @@ -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 void delete() throws IOException { 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; diff --git a/src/main/java/org/kohsuke/github/GHRelease.java b/src/main/java/org/kohsuke/github/GHRelease.java index 86736e909d..6b30a062de 100644 --- a/src/main/java/org/kohsuke/github/GHRelease.java +++ b/src/main/java/org/kohsuke/github/GHRelease.java @@ -70,7 +70,7 @@ public boolean isPrerelease() { } public Date getPublished_at() { - return published_at; + return new Date(published_at.getTime()); } public GitHub getRoot() { @@ -123,9 +123,14 @@ public GHAsset uploadAsset(File file, String contentType) throws IOException { 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 getAssets() throws IOException { diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 5acf0a648b..54acc2c8c3 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -25,6 +25,7 @@ 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,7 +34,9 @@ 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; @@ -44,6 +47,8 @@ * @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; @@ -217,7 +222,8 @@ public List getIssues(GHIssueState state) throws IOException { public List 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)); } @@ -383,7 +389,8 @@ public String getMasterBranch() { public int getSize() { return size; } - + + /** * Gets the collaborators on this repository. * This set always appear to include the owner. @@ -950,6 +957,8 @@ private void verifyMine() throws IOException { * @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 getPostCommitHooks() { return postCommitHooks; } @@ -957,6 +966,8 @@ public Set getPostCommitHooks() { /** * 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 postCommitHooks = new AbstractSet() { private List getPostCommitHooks() { try { @@ -1101,11 +1112,17 @@ public GHContent getReadme() throws IOException { } 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 { @@ -1225,6 +1242,18 @@ public static class Contributor extends GHUser { 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); + } } /** diff --git a/src/main/java/org/kohsuke/github/GHTag.java b/src/main/java/org/kohsuke/github/GHTag.java index 3a72407754..802f51f8f3 100644 --- a/src/main/java/org/kohsuke/github/GHTag.java +++ b/src/main/java/org/kohsuke/github/GHTag.java @@ -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; diff --git a/src/main/java/org/kohsuke/github/GHThread.java b/src/main/java/org/kohsuke/github/GHThread.java index 6a2608f253..a1964b10de 100644 --- a/src/main/java/org/kohsuke/github/GHThread.java +++ b/src/main/java/org/kohsuke/github/GHThread.java @@ -1,5 +1,6 @@ package org.kohsuke.github; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.io.FileNotFoundException; import java.io.IOException; import java.net.URL; @@ -12,6 +13,8 @@ * @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; @@ -67,6 +70,10 @@ public String getTitle() { public String getType() { return subject.type; } + + public String getLastCommentUrl() { + return subject.latest_comment_url; + } /** * If this thread is about an issue, return that issue. diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index d3853380e8..9e638bb4aa 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -53,6 +53,7 @@ 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. @@ -128,7 +129,13 @@ 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; } diff --git a/src/main/java/org/kohsuke/github/GitUser.java b/src/main/java/org/kohsuke/github/GitUser.java index fc97ef8882..751aabd378 100644 --- a/src/main/java/org/kohsuke/github/GitUser.java +++ b/src/main/java/org/kohsuke/github/GitUser.java @@ -1,5 +1,6 @@ package org.kohsuke.github; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.util.Date; /** @@ -11,6 +12,8 @@ * * @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; diff --git a/src/main/java/org/kohsuke/github/PagedSearchIterable.java b/src/main/java/org/kohsuke/github/PagedSearchIterable.java index 65b6c7490d..222cedcd00 100644 --- a/src/main/java/org/kohsuke/github/PagedSearchIterable.java +++ b/src/main/java/org/kohsuke/github/PagedSearchIterable.java @@ -1,5 +1,6 @@ package org.kohsuke.github; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.util.Iterator; /** @@ -7,6 +8,8 @@ * * @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 extends PagedIterable { private final GitHub root; diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index 281426dd3e..78ead072d9 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -119,7 +119,7 @@ public Requester with(String key, int value) { public Requester with(String key, Integer value) { if (value!=null) - _with(key, value.intValue()); + _with(key, value); return this; } @@ -323,23 +323,26 @@ private boolean isMethodWithBody() { * * Every iterator call reports a new batch. */ - /*package*/ Iterator asIterator(String _tailApiUrl, final Class type) { + /*package*/ Iterator asIterator(final String _tailApiUrl, final Class 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() { /** @@ -507,11 +510,4 @@ private InputStream wrapStream(InputStream in) throws IOException { IOUtils.closeQuietly(es); } } - - private Set toSet(String s) { - Set r = new HashSet(); - for (String t : s.split(",")) - r.add(t.trim()); - return r; - } } diff --git a/src/main/java/org/kohsuke/github/SearchResult.java b/src/main/java/org/kohsuke/github/SearchResult.java index a8a7583a4c..7b9f9a0c59 100644 --- a/src/main/java/org/kohsuke/github/SearchResult.java +++ b/src/main/java/org/kohsuke/github/SearchResult.java @@ -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 { + @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; /** From 76d28314b01c1da9455e3179f243bb60169e46c6 Mon Sep 17 00:00:00 2001 From: Uros Majeric Date: Thu, 6 Aug 2015 15:40:26 +0200 Subject: [PATCH 040/390] Added option to edit GitHub release once it is created --- src/main/java/org/kohsuke/github/GHRelease.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHRelease.java b/src/main/java/org/kohsuke/github/GHRelease.java index 6b30a062de..901bb8f359 100644 --- a/src/main/java/org/kohsuke/github/GHRelease.java +++ b/src/main/java/org/kohsuke/github/GHRelease.java @@ -45,6 +45,12 @@ public boolean isDraft() { return draft; } + public GHRelease setDraft(boolean draft) throws IOException { + edit("draft", draft); + this.draft = draft; + return this; + } + public URL getHtmlUrl() { return GitHub.parseURL(html_url); } @@ -149,6 +155,13 @@ public void delete() throws IOException { 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)); } From 2bcd99b14f434c65f1b545adc18ef5f82a147505 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 14 Aug 2015 11:53:48 -0700 Subject: [PATCH 041/390] Overzealous findbugs fix. This method should rely on platform specific encoding --- src/main/java/org/kohsuke/github/GHContent.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHContent.java b/src/main/java/org/kohsuke/github/GHContent.java index bc96af5ddc..0fbb59484f 100644 --- a/src/main/java/org/kohsuke/github/GHContent.java +++ b/src/main/java/org/kohsuke/github/GHContent.java @@ -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,8 +76,9 @@ public String getPath() { * @deprecated * Use {@link #read()} */ + @SuppressFBWarnings("DM_DEFAULT_ENCODING") public String getContent() throws IOException { - return new String(DatatypeConverter.parseBase64Binary(getEncodedContent()), getEncoding()); + return new String(DatatypeConverter.parseBase64Binary(getEncodedContent())); } /** From 839cb03690f75f1bc0c713751d0c1ce8eb0fedbb Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 15 Aug 2015 07:17:15 -0700 Subject: [PATCH 042/390] 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! --- src/main/java/org/kohsuke/github/GHContent.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHContent.java b/src/main/java/org/kohsuke/github/GHContent.java index 0fbb59484f..c79e00e384 100644 --- a/src/main/java/org/kohsuke/github/GHContent.java +++ b/src/main/java/org/kohsuke/github/GHContent.java @@ -163,12 +163,14 @@ protected void wrapUp(GHContent[] page) { }; } + @SuppressFBWarnings("DM_DEFAULT_ENCODING") public GHContentUpdateResponse update(String newContent, String commitMessage) throws IOException { - return update(newContent.getBytes(getEncoding()), commitMessage, null); + 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(getEncoding()), commitMessage, branch); + return update(newContent.getBytes(), commitMessage, branch); } public GHContentUpdateResponse update(byte[] newContentBytes, String commitMessage) throws IOException { From 6516b20e160c5cda2ddb3843f922d792fbf2ad25 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 15 Aug 2015 07:19:22 -0700 Subject: [PATCH 043/390] [maven-release-plugin] prepare release github-api-1.70 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 83d8d07083..6650872541 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.70-SNAPSHOT + 1.70 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - HEAD + github-api-1.70 From adaa8ece89ae8d6652d8f3c2b934af5caf7bb2bd Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 15 Aug 2015 07:19:25 -0700 Subject: [PATCH 044/390] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 6650872541..60299712b2 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.70 + 1.71-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - github-api-1.70 + HEAD From e0b109cba6faa84813a528880dbf3923c1b86058 Mon Sep 17 00:00:00 2001 From: Rob Schoening Date: Tue, 1 Sep 2015 00:00:46 -0700 Subject: [PATCH 045/390] fix read() failure with private repos reorder buildRequest() --- src/main/java/org/kohsuke/github/Requester.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index 78ead072d9..12fd96fa66 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -271,8 +271,12 @@ public InputStream asStream(String tailApiUrl) throws IOException { while (true) {// loop while API rate limit is hit setupConnection(root.getApiURL(tailApiUrl)); - buildRequest(); - + + // if the download link is encoded with a token on the query string, the default behavior of POST will fail + uc.setRequestMethod("GET"); + + buildRequest(); + try { return wrapStream(uc.getInputStream()); } catch (IOException e) { From b0687dbeb59f5c9202f9b1c9cff0aceb4d760a55 Mon Sep 17 00:00:00 2001 From: Rob Schoening Date: Sun, 6 Sep 2015 08:45:42 -0700 Subject: [PATCH 046/390] Fix compilation errror: The constructor ArrayList(List) is undefined --- src/main/java/org/kohsuke/github/GHHooks.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHHooks.java b/src/main/java/org/kohsuke/github/GHHooks.java index 1a6154aa6d..4ee939c5a8 100644 --- a/src/main/java/org/kohsuke/github/GHHooks.java +++ b/src/main/java/org/kohsuke/github/GHHooks.java @@ -21,8 +21,9 @@ private Context(GitHub root) { } public List getHooks() throws IOException { - List list = new ArrayList(Arrays.asList( - root.retrieve().to(collection(), collectionClass()))); + + GHHook [] hookArray = root.retrieve().to(collection(),collectionClass()); // jdk/eclipse bug requires this to be on separate line + List list = new ArrayList(Arrays.asList(hookArray)); for (GHHook h : list) wrap(h); return list; From 025b6cbfb799fdbbd4aefb4b09953054d4c35831 Mon Sep 17 00:00:00 2001 From: dblevins Date: Mon, 14 Sep 2015 10:53:07 -0700 Subject: [PATCH 047/390] Support Milestone closed_at date --- src/main/java/org/kohsuke/github/GHMilestone.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHMilestone.java b/src/main/java/org/kohsuke/github/GHMilestone.java index 146c92abb3..0d1b43224e 100644 --- a/src/main/java/org/kohsuke/github/GHMilestone.java +++ b/src/main/java/org/kohsuke/github/GHMilestone.java @@ -17,6 +17,7 @@ public class GHMilestone extends GHObject { GHUser creator; private String state, due_on, title, description, html_url; private int closed_issues, open_issues, number; + protected String closed_at; public GitHub getRoot() { return root; @@ -34,7 +35,14 @@ public Date getDueOn() { if (due_on == null) return null; return GitHub.parseDate(due_on); } - + + /** + * When was this milestone closed? + */ + public Date getClosedAt() throws IOException { + return GitHub.parseDate(closed_at); + } + public String getTitle() { return title; } From 512c921a814e2700b1bb8926fdbf0949cfe3137c Mon Sep 17 00:00:00 2001 From: Rob Schoening Date: Sun, 20 Sep 2015 21:20:57 -0700 Subject: [PATCH 048/390] enable cross fork compare --- .../java/org/kohsuke/github/GHRepository.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 54acc2c8c3..8f45a5b92a 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -682,7 +682,23 @@ public GHCompare getCompare(GHCommit id1, GHCommit id2) throws IOException { } public GHCompare getCompare(GHBranch id1, GHBranch id2) throws IOException { - return getCompare(id1.getName(),id2.getName()); + + GHRepository owner1 = id1.getOwner(); + GHRepository owner2 = id2.getOwner(); + + // If the owner of the branches is different, we have a cross-fork compare. + if (owner1!=null && owner2!=null) { + String ownerName1 = owner1.getOwnerName(); + String ownerName2 = owner2.getOwnerName(); + if (!StringUtils.equals(ownerName1, ownerName2)) { + String qualifiedName1 = String.format("%s:%s", ownerName1, id1.getName()); + String qualifiedName2 = String.format("%s:%s", ownerName2, id2.getName()); + return getCompare(qualifiedName1, qualifiedName2); + } + } + + return getCompare(id1.getName(), id2.getName()); + } /** From 092e9062c814da19f1ab2d3f18292c5dd131104f Mon Sep 17 00:00:00 2001 From: Ruben Dijkstra Date: Tue, 6 Oct 2015 09:33:29 +0200 Subject: [PATCH 049/390] Remove trailing slash when requesting directory content --- src/main/java/org/kohsuke/github/GHRepository.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 54acc2c8c3..f48abbd311 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -1094,6 +1094,9 @@ public List getDirectoryContent(String path) throws IOException { public List getDirectoryContent(String path, String ref) throws IOException { Requester requester = root.retrieve(); + while (path.endsWith("/")) { + path = path.substring(0, path.length() - 1); + } String target = getApiTailUrl("contents/" + path); GHContent[] files = requester.with("ref",ref).to(target, GHContent[].class); From 5dc83cf2bf1ba8e945986a7e9fb156332ab138ee Mon Sep 17 00:00:00 2001 From: Ruben Dijkstra Date: Wed, 7 Oct 2015 09:38:48 +0200 Subject: [PATCH 050/390] Overzealous FindBugs changes. Charsets that are standard on the JRE are try-lookuped, bridge methods were removed and a stream that would be closed later is closed explicitly --- src/main/java/org/kohsuke/github/GHObject.java | 15 +++++++++++++++ src/main/java/org/kohsuke/github/GHRelease.java | 9 ++------- src/main/java/org/kohsuke/github/GitHub.java | 8 ++------ src/main/java/org/kohsuke/github/Requester.java | 4 +++- 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHObject.java b/src/main/java/org/kohsuke/github/GHObject.java index 50aa0a6a86..270ac1fcc5 100644 --- a/src/main/java/org/kohsuke/github/GHObject.java +++ b/src/main/java/org/kohsuke/github/GHObject.java @@ -29,6 +29,11 @@ public Date getCreatedAt() throws IOException { return GitHub.parseDate(created_at); } + @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD", justification = "Bridge method of getCreatedAt") + private Object createdAtStr(Date id, Class type) { + return created_at; + } + /** * API URL of this object. */ @@ -57,4 +62,14 @@ public Date getUpdatedAt() throws IOException { public int getId() { return id; } + + @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD", justification = "Bridge method of getId") + private Object intToString(int id, Class type) { + return String.valueOf(id); + } + + @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD", justification = "Bridge method of getHtmlUrl") + private Object urlToString(URL url, Class type) { + return url==null ? null : url.toString(); + } } diff --git a/src/main/java/org/kohsuke/github/GHRelease.java b/src/main/java/org/kohsuke/github/GHRelease.java index 901bb8f359..b61dc62b38 100644 --- a/src/main/java/org/kohsuke/github/GHRelease.java +++ b/src/main/java/org/kohsuke/github/GHRelease.java @@ -129,14 +129,9 @@ public GHAsset uploadAsset(File file, String contentType) throws IOException { String url = format("https://uploads.github.com%s/releases/%d/assets?name=%s", owner.getApiTailUrl(""), getId(), file.getName()); - FileInputStream istream = new FileInputStream(file); - try { - return builder.contentType(contentType) - .with(istream) + return builder.contentType(contentType) + .with(new FileInputStream(file)) .to(url, GHAsset.class).wrap(this); - } finally { - istream.close(); - } } public List getAssets() throws IOException { diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 9e638bb4aa..2eaef53ceb 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -47,6 +47,7 @@ import java.util.TimeZone; import java.util.concurrent.TimeUnit; +import org.apache.commons.codec.Charsets; import org.apache.commons.codec.binary.Base64; import com.fasterxml.jackson.databind.DeserializationFeature; @@ -129,12 +130,7 @@ public class GitHub { } else { if (password!=null) { String authorization = (login + ':' + password); - final Charset charset; - try { - charset = Charset.forName("UTF-8"); - } catch (Exception ex) { - throw new IOException("UTF-8 encoding is not supported", ex); - } + Charset charset = Charsets.UTF_8; encodedAuthorization = "Basic "+new String(Base64.encodeBase64(authorization.getBytes(charset)), charset); } else {// anonymous access encodedAuthorization = null; diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index 78ead072d9..b8b53b78cd 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -53,6 +53,8 @@ import java.util.regex.Pattern; import java.util.zip.GZIPInputStream; +import javax.annotation.WillClose; + import static java.util.Arrays.asList; import static org.kohsuke.github.GitHub.*; @@ -143,7 +145,7 @@ public Requester with(String key, Map value) { return _with(key, value); } - public Requester with(InputStream body) { + public Requester with(@WillClose/*later*/ InputStream body) { this.body = body; return this; } From 75b9184a0011a5d900698e1d119105b2543a5047 Mon Sep 17 00:00:00 2001 From: Ruben Dijkstra Date: Fri, 9 Oct 2015 12:31:08 +0200 Subject: [PATCH 051/390] Check builder result to either be a token or a user Currently, a `user` property is always required (it not having content is also fine). This adds support for only having the `oauth` key in the property file/environment. --- src/main/java/org/kohsuke/github/GitHubBuilder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GitHubBuilder.java b/src/main/java/org/kohsuke/github/GitHubBuilder.java index c0ecaffda5..9160976640 100644 --- a/src/main/java/org/kohsuke/github/GitHubBuilder.java +++ b/src/main/java/org/kohsuke/github/GitHubBuilder.java @@ -51,7 +51,7 @@ public static GitHubBuilder fromCredentials() throws IOException { try { builder = fromPropertyFile(); - if (builder.user != null) + if (builder.oauthToken != null || builder.user != null) return builder; } catch (FileNotFoundException e) { // fall through @@ -60,7 +60,7 @@ public static GitHubBuilder fromCredentials() throws IOException { builder = fromEnvironment(); - if (builder.user != null) + if (builder.oauthToken != null || builder.user != null) return builder; else throw (IOException)new IOException("Failed to resolve credentials from ~/.github or the environment.").initCause(cause); From bafddf4bafc9f897f2c0dbb9d4e42de244e08ead Mon Sep 17 00:00:00 2001 From: Manuel Recena Date: Sat, 14 Nov 2015 12:11:24 +0100 Subject: [PATCH 052/390] Initial source code modifications --- src/main/java/org/kohsuke/github/GHPullRequest.java | 12 +++++++++--- .../java/org/kohsuke/github/PullRequestTest.java | 9 +++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index 909110b727..42cc38992e 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -50,6 +50,7 @@ public class GHPullRequest extends GHIssue { private int deletions; private String mergeable_state; private int changed_files; + private String merge_commit_sha; /** * GitHub doesn't return some properties of {@link GHIssue} when requesting the GET on the 'pulls' API @@ -142,9 +143,9 @@ public PullRequest getPullRequest() { } // -// details that are only available via get with ID -// -// + // details that are only available via get with ID + // + public GHUser getMergedBy() throws IOException { populate(); return merged_by; @@ -185,6 +186,11 @@ public int getChangedFiles() throws IOException { return changed_files; } + public String getMergeCommitSha() throws IOException { + populate(); + return merge_commit_sha; + } + /** * Fully populate the data by retrieving missing data. * diff --git a/src/test/java/org/kohsuke/github/PullRequestTest.java b/src/test/java/org/kohsuke/github/PullRequestTest.java index 9fc55f7519..9ef582cb79 100644 --- a/src/test/java/org/kohsuke/github/PullRequestTest.java +++ b/src/test/java/org/kohsuke/github/PullRequestTest.java @@ -49,6 +49,15 @@ public void testPullRequestReviewComments() throws Exception { assertTrue(comments.isEmpty()); } + @Test + public void testMergeCommitSHA() throws Exception { + String name = rnd.next(); + GHRepository repo = gitHub.getMyself().getRepository("website"); + GHPullRequest p = repo.createPullRequest(name, "feature5", "master", "## test"); + GHRef ref = repo.getRef("pull/" + p.getNumber() + "/merge"); + assertTrue(ref.getObject().getSha() == p.getMergeCommitSha()); + } + @Test // Requires push access to the test repo to pass public void setLabels() throws Exception { From 08be8eb4f8ae4b202c7ab74de51958c632a13223 Mon Sep 17 00:00:00 2001 From: Manuel Recena Date: Sun, 15 Nov 2015 11:46:18 +0100 Subject: [PATCH 053/390] Added a new test testMergeCommitSHA() --- src/test/java/org/kohsuke/github/PullRequestTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/java/org/kohsuke/github/PullRequestTest.java b/src/test/java/org/kohsuke/github/PullRequestTest.java index 9ef582cb79..4ed9dd5b0f 100644 --- a/src/test/java/org/kohsuke/github/PullRequestTest.java +++ b/src/test/java/org/kohsuke/github/PullRequestTest.java @@ -52,10 +52,10 @@ public void testPullRequestReviewComments() throws Exception { @Test public void testMergeCommitSHA() throws Exception { String name = rnd.next(); - GHRepository repo = gitHub.getMyself().getRepository("website"); - GHPullRequest p = repo.createPullRequest(name, "feature5", "master", "## test"); - GHRef ref = repo.getRef("pull/" + p.getNumber() + "/merge"); - assertTrue(ref.getObject().getSha() == p.getMergeCommitSha()); + GHPullRequest p = getRepository().createPullRequest(name, "stable", "master", "## test"); + GHPullRequest updated = getRepository().getPullRequest(p.getNumber()); + GHCommit commit = getRepository().getCommit(updated.getMergeCommitSha()); + assertNotNull(commit); } @Test From b0789a7ce72b6e1773b47d4e778535f839863480 Mon Sep 17 00:00:00 2001 From: Manuel Recena Date: Sun, 15 Nov 2015 11:50:13 +0100 Subject: [PATCH 054/390] Set merge_commit_sha as deprecated --- src/main/java/org/kohsuke/github/GHPullRequest.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index 42cc38992e..b9078d9c30 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -50,6 +50,8 @@ public class GHPullRequest extends GHIssue { private int deletions; private String mergeable_state; private int changed_files; + + @Deprecated private String merge_commit_sha; /** @@ -186,6 +188,10 @@ public int getChangedFiles() throws IOException { return changed_files; } + /** + * FYI: https://developer.github.com/changes/2013-04-25-deprecating-merge-commit-sha + */ + @Deprecated public String getMergeCommitSha() throws IOException { populate(); return merge_commit_sha; From a371892409621e50a9d9c5c11d8045cfc1396d34 Mon Sep 17 00:00:00 2001 From: Manuel Recena Date: Sun, 15 Nov 2015 16:36:27 +0100 Subject: [PATCH 055/390] Added a new method to validate the GitHub API URL --- pom.xml | 3 +-- .../java/org/kohsuke/github/GHApiInfo.java | 14 ++++++++++ src/main/java/org/kohsuke/github/GitHub.java | 26 +++++++++++++++++++ .../java/org/kohsuke/github/GitHubTest.java | 7 +++++ 4 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 src/main/java/org/kohsuke/github/GHApiInfo.java diff --git a/pom.xml b/pom.xml index 60299712b2..02b788b6a4 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ UTF-8 - 3.0.1 + 3.0.2 true @@ -52,7 +52,6 @@ ${findbugs-maven-plugin.version} true - true ${findbugs-maven-plugin.failOnError} diff --git a/src/main/java/org/kohsuke/github/GHApiInfo.java b/src/main/java/org/kohsuke/github/GHApiInfo.java new file mode 100644 index 0000000000..131e0de647 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHApiInfo.java @@ -0,0 +1,14 @@ +package org.kohsuke.github; + +/** + * Represents information about Github API. + */ +public class GHApiInfo { + + private String rate_limit_url; + + public String getRateLimitUrl() { + return rate_limit_url; + } + +} diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 9e638bb4aa..1ca5ed968e 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -204,6 +204,15 @@ public static GitHub connectAnonymously() throws IOException { return new GitHubBuilder().build(); } + /** + * Connects to GitHub Enterprise anonymously. + * + * All operations that requires authentication will fail. + */ + public static GitHub connectToEnterpriseAnonymously(String apiUrl) throws IOException { + return new GitHubBuilder().withEndpoint(apiUrl).build(); + } + /** * Is this an anonymous connection * @return {@code true} if operations that require authentication will fail. @@ -446,6 +455,23 @@ public boolean isCredentialValid() throws IOException { } } + /** + * Ensures that the API URL is valid. + */ + public boolean isApiUrlValid() throws IOException { + try { + GHApiInfo apiInfo = retrieve().to("/", GHApiInfo.class); + try { + new URL(apiInfo.getRateLimitUrl()); + return true; + } catch (MalformedURLException mue) { + return false; + } + } catch (IOException e) { + return false; + } + } + /** * Search issues. */ diff --git a/src/test/java/org/kohsuke/github/GitHubTest.java b/src/test/java/org/kohsuke/github/GitHubTest.java index 54ce6e35d7..5c5ee982fe 100644 --- a/src/test/java/org/kohsuke/github/GitHubTest.java +++ b/src/test/java/org/kohsuke/github/GitHubTest.java @@ -12,6 +12,7 @@ import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; @@ -119,4 +120,10 @@ public void testGitHubEnterpriseDoesNotHaveRateLimit() throws IOException { GHRateLimit rateLimit = github.getRateLimit(); assertThat(rateLimit.getResetDate(), notNullValue()); } + + @Test + public void testGitHubIsApiUrlValid() throws IOException { + GitHub github = GitHub.connectAnonymously(); + assertTrue(github.isApiUrlValid()); + } } From 354969d5fae984af50a648cded5300e04cf3d512 Mon Sep 17 00:00:00 2001 From: Manuel Recena Date: Mon, 16 Nov 2015 11:16:58 +0100 Subject: [PATCH 056/390] Javadoc comment reviewed --- src/main/java/org/kohsuke/github/GHPullRequest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index b9078d9c30..8d1f0cab2f 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -189,7 +189,7 @@ public int getChangedFiles() throws IOException { } /** - * FYI: https://developer.github.com/changes/2013-04-25-deprecating-merge-commit-sha + * See GitHub blog post */ @Deprecated public String getMergeCommitSha() throws IOException { From a1e79d305037afebc0aefbcefd7598814083051a Mon Sep 17 00:00:00 2001 From: Ruben Dijkstra Date: Mon, 16 Nov 2015 18:33:51 +0100 Subject: [PATCH 057/390] Add unit test to cover the truncation of ?ref --- .../java/org/kohsuke/github/GHContentIntegrationTest.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/test/java/org/kohsuke/github/GHContentIntegrationTest.java b/src/test/java/org/kohsuke/github/GHContentIntegrationTest.java index 39f8545aaa..7848143a86 100644 --- a/src/test/java/org/kohsuke/github/GHContentIntegrationTest.java +++ b/src/test/java/org/kohsuke/github/GHContentIntegrationTest.java @@ -43,6 +43,14 @@ public void testGetDirectoryContent() throws Exception { assertTrue(entries.size() == 3); } + @Test + public void testGetDirectoryContentTrailingSlash() throws Exception { + //Used to truncate the ?ref=master, see gh-224 https://github.com/kohsuke/github-api/pull/224 + List entries = repo.getDirectoryContent("ghcontent-ro/a-dir-with-3-entries/", "master"); + + assertTrue(entries.get(0).getUrl().endsWith("?ref=master")); + } + @Test public void testCRUDContent() throws Exception { GHContentUpdateResponse created = repo.createContent("this is an awesome file I created\n", "Creating a file for integration tests.", createdFilename); From b037f75fb0e897046360f6333f0cbbc2763ba4e8 Mon Sep 17 00:00:00 2001 From: Vitaly Parfonov Date: Thu, 19 Nov 2015 12:09:34 +0200 Subject: [PATCH 058/390] Add information about mirror url if it exist. Like https://github.com/apache/tomee --- src/main/java/org/kohsuke/github/GHRepository.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 54acc2c8c3..f77ac6e2e8 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -54,7 +54,7 @@ public class GHRepository extends GHObject { private String description, homepage, name, full_name; private String html_url; // this is the UI - private String git_url, ssh_url, clone_url, svn_url; + private String git_url, ssh_url, clone_url, svn_url, mirror_url; private GHUser owner; // not fully populated. beware. private boolean has_issues, has_wiki, fork, has_downloads; @JsonProperty("private") @@ -159,6 +159,14 @@ public String getSvnUrl() { return svn_url; } + /** + * Gets the Mirror URL to access this repository: https://github.com/apache/tomee + * mirrored from git://git.apache.org/tomee.git + */ + public String getMirrorUrl() { + return mirror_url; + } + /** * Gets the SSH URL to access this repository, such as git@github.com:rails/rails.git */ From c6d2b1a22257f15963d3e4bd79929af10670b918 Mon Sep 17 00:00:00 2001 From: Manuel Recena Date: Mon, 23 Nov 2015 09:33:32 +0100 Subject: [PATCH 059/390] @deprecated annotations were removed --- src/main/java/org/kohsuke/github/GHPullRequest.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index 8d1f0cab2f..5604d2355e 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -50,8 +50,6 @@ public class GHPullRequest extends GHIssue { private int deletions; private String mergeable_state; private int changed_files; - - @Deprecated private String merge_commit_sha; /** @@ -191,7 +189,6 @@ public int getChangedFiles() throws IOException { /** * See GitHub blog post */ - @Deprecated public String getMergeCommitSha() throws IOException { populate(); return merge_commit_sha; From acbafee02afcb4f46f6f379c2dbe65742c140c63 Mon Sep 17 00:00:00 2001 From: Manuel Recena Date: Mon, 23 Nov 2015 10:25:41 +0100 Subject: [PATCH 060/390] Removed unrelated changes. @KostyaSha's suggestion --- pom.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 02b788b6a4..60299712b2 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ UTF-8 - 3.0.2 + 3.0.1 true @@ -52,6 +52,7 @@ ${findbugs-maven-plugin.version} true + true ${findbugs-maven-plugin.failOnError} From aab21c5b170d24f1cca0010803e19677718e8b73 Mon Sep 17 00:00:00 2001 From: Manuel Recena Date: Mon, 23 Nov 2015 10:29:04 +0100 Subject: [PATCH 061/390] findbugs plugin has been upgraded --- pom.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 60299712b2..02b788b6a4 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ UTF-8 - 3.0.1 + 3.0.2 true @@ -52,7 +52,6 @@ ${findbugs-maven-plugin.version} true - true ${findbugs-maven-plugin.failOnError} From 75a40815498fa370e81ad3bc60fb769eb8c7ce1f Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Tue, 1 Dec 2015 14:57:30 +0100 Subject: [PATCH 062/390] Follow up to PR #216 --- src/main/java/org/kohsuke/github/Requester.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index 92f069bdfe..81fe507d8b 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -259,6 +259,8 @@ public int asHttpStatusCode(String tailApiUrl) throws IOException { while (true) {// loop while API rate limit is hit setupConnection(root.getApiURL(tailApiUrl)); + uc.setRequestMethod("GET"); + buildRequest(); try { @@ -273,7 +275,6 @@ public InputStream asStream(String tailApiUrl) throws IOException { while (true) {// loop while API rate limit is hit setupConnection(root.getApiURL(tailApiUrl)); - // if the download link is encoded with a token on the query string, the default behavior of POST will fail uc.setRequestMethod("GET"); From 832e4f3c37e58b2c36195c899d50b69686f12c77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20Gond=C5=BEa?= Date: Tue, 1 Dec 2015 14:58:46 +0100 Subject: [PATCH 063/390] Use default timeouts for URLConnections --- src/main/java/org/kohsuke/github/GitHubBuilder.java | 5 ++++- src/main/java/org/kohsuke/github/HttpConnector.java | 9 ++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GitHubBuilder.java b/src/main/java/org/kohsuke/github/GitHubBuilder.java index c0ecaffda5..0056b87987 100644 --- a/src/main/java/org/kohsuke/github/GitHubBuilder.java +++ b/src/main/java/org/kohsuke/github/GitHubBuilder.java @@ -186,7 +186,10 @@ public GitHubBuilder withRateLimitHandler(RateLimitHandler handler) { public GitHubBuilder withProxy(final Proxy p) { return withConnector(new HttpConnector() { public HttpURLConnection connect(URL url) throws IOException { - return (HttpURLConnection) url.openConnection(p); + HttpURLConnection con = (HttpURLConnection) url.openConnection(p); + con.setConnectTimeout(HttpConnector.HTTP_CONNECT_TIMEOUT); + con.setReadTimeout(HttpConnector.HTTP_READ_TIMEOUT); + return con; } }); } diff --git a/src/main/java/org/kohsuke/github/HttpConnector.java b/src/main/java/org/kohsuke/github/HttpConnector.java index 6cff72dc53..555fba34fb 100644 --- a/src/main/java/org/kohsuke/github/HttpConnector.java +++ b/src/main/java/org/kohsuke/github/HttpConnector.java @@ -3,6 +3,7 @@ import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; +import java.util.concurrent.TimeUnit; /** * Pluggability for customizing HTTP request behaviors or using altogether different library. @@ -23,7 +24,13 @@ public interface HttpConnector { */ HttpConnector DEFAULT = new HttpConnector() { public HttpURLConnection connect(URL url) throws IOException { - return (HttpURLConnection) url.openConnection(); + HttpURLConnection con = (HttpURLConnection) url.openConnection(); + con.setConnectTimeout(HTTP_CONNECT_TIMEOUT); + con.setReadTimeout(HTTP_READ_TIMEOUT); + return con; } }; + + int HTTP_CONNECT_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(10); + int HTTP_READ_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(10); } From 261a7a34e36964e8bffdd60cd4ceaf8b79d93628 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Tue, 1 Dec 2015 15:17:54 +0100 Subject: [PATCH 064/390] Consolidated timeout handling --- .../org/kohsuke/github/GitHubBuilder.java | 10 ++-- .../org/kohsuke/github/HttpConnector.java | 14 ++--- .../github/extras/ImpatientHttpConnector.java | 54 +++++++++++++++++++ 3 files changed, 63 insertions(+), 15 deletions(-) create mode 100644 src/main/java/org/kohsuke/github/extras/ImpatientHttpConnector.java diff --git a/src/main/java/org/kohsuke/github/GitHubBuilder.java b/src/main/java/org/kohsuke/github/GitHubBuilder.java index 0056b87987..0b85871eaf 100644 --- a/src/main/java/org/kohsuke/github/GitHubBuilder.java +++ b/src/main/java/org/kohsuke/github/GitHubBuilder.java @@ -1,6 +1,7 @@ package org.kohsuke.github; import org.apache.commons.io.IOUtils; +import org.kohsuke.github.extras.ImpatientHttpConnector; import java.io.File; import java.io.FileInputStream; @@ -184,14 +185,11 @@ public GitHubBuilder withRateLimitHandler(RateLimitHandler handler) { * the system default one. */ public GitHubBuilder withProxy(final Proxy p) { - return withConnector(new HttpConnector() { + return withConnector(new ImpatientHttpConnector(new HttpConnector() { public HttpURLConnection connect(URL url) throws IOException { - HttpURLConnection con = (HttpURLConnection) url.openConnection(p); - con.setConnectTimeout(HttpConnector.HTTP_CONNECT_TIMEOUT); - con.setReadTimeout(HttpConnector.HTTP_READ_TIMEOUT); - return con; + return (HttpURLConnection) url.openConnection(p); } - }); + })); } public GitHub build() throws IOException { diff --git a/src/main/java/org/kohsuke/github/HttpConnector.java b/src/main/java/org/kohsuke/github/HttpConnector.java index 555fba34fb..5496268561 100644 --- a/src/main/java/org/kohsuke/github/HttpConnector.java +++ b/src/main/java/org/kohsuke/github/HttpConnector.java @@ -1,5 +1,7 @@ package org.kohsuke.github; +import org.kohsuke.github.extras.ImpatientHttpConnector; + import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; @@ -22,15 +24,9 @@ public interface HttpConnector { /** * Default implementation that uses {@link URL#openConnection()}. */ - HttpConnector DEFAULT = new HttpConnector() { + HttpConnector DEFAULT = new ImpatientHttpConnector(new HttpConnector() { public HttpURLConnection connect(URL url) throws IOException { - HttpURLConnection con = (HttpURLConnection) url.openConnection(); - con.setConnectTimeout(HTTP_CONNECT_TIMEOUT); - con.setReadTimeout(HTTP_READ_TIMEOUT); - return con; + return (HttpURLConnection) url.openConnection(); } - }; - - int HTTP_CONNECT_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(10); - int HTTP_READ_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(10); + }); } diff --git a/src/main/java/org/kohsuke/github/extras/ImpatientHttpConnector.java b/src/main/java/org/kohsuke/github/extras/ImpatientHttpConnector.java new file mode 100644 index 0000000000..e0e18fc962 --- /dev/null +++ b/src/main/java/org/kohsuke/github/extras/ImpatientHttpConnector.java @@ -0,0 +1,54 @@ +package org.kohsuke.github.extras; + +import org.kohsuke.github.HttpConnector; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.concurrent.TimeUnit; + +/** + * {@link HttpConnector} wrapper that sets timeout + * + * @author Kohsuke Kawaguchi + */ +public class ImpatientHttpConnector implements HttpConnector { + private final HttpConnector base; + private final int readTimeout, connectTimeout; + + /** + * @param connectTimeout + * HTTP connection timeout in milliseconds + * @param readTimeout + * HTTP read timeout in milliseconds + */ + public ImpatientHttpConnector(HttpConnector base, int connectTimeout, int readTimeout) { + this.base = base; + this.connectTimeout = connectTimeout; + this.readTimeout = readTimeout; + } + + public ImpatientHttpConnector(HttpConnector base, int timeout) { + this(base,timeout,timeout); + } + + public ImpatientHttpConnector(HttpConnector base) { + this(base,CONNECT_TIMEOUT,READ_TIMEOUT); + } + + public HttpURLConnection connect(URL url) throws IOException { + HttpURLConnection con = base.connect(url); + con.setConnectTimeout(connectTimeout); + con.setReadTimeout(readTimeout); + return con; + } + + /** + * Default connection timeout in milliseconds + */ + public static int CONNECT_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(10); + /** + * Default read timeout in milliseconds + */ + public static int READ_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(10); +} From 0397d7ab53fa6c7489115de024f3dc0c40c80484 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Tue, 1 Dec 2015 15:39:19 +0100 Subject: [PATCH 065/390] Fixing a test problem --- .../org/kohsuke/github/PullRequestTest.java | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/test/java/org/kohsuke/github/PullRequestTest.java b/src/test/java/org/kohsuke/github/PullRequestTest.java index 4ed9dd5b0f..c7ce77d289 100644 --- a/src/test/java/org/kohsuke/github/PullRequestTest.java +++ b/src/test/java/org/kohsuke/github/PullRequestTest.java @@ -52,10 +52,21 @@ public void testPullRequestReviewComments() throws Exception { @Test public void testMergeCommitSHA() throws Exception { String name = rnd.next(); - GHPullRequest p = getRepository().createPullRequest(name, "stable", "master", "## test"); - GHPullRequest updated = getRepository().getPullRequest(p.getNumber()); - GHCommit commit = getRepository().getCommit(updated.getMergeCommitSha()); - assertNotNull(commit); + GHPullRequest p = getRepository().createPullRequest(name, "mergeable-branch", "master", "## test"); + for (int i=0; i<100; i++) { + GHPullRequest updated = getRepository().getPullRequest(p.getNumber()); + if (updated.getMergeCommitSha()!=null) { + // make sure commit exists + GHCommit commit = getRepository().getCommit(updated.getMergeCommitSha()); + assertNotNull(commit); + return; + } + + // mergeability computation takes time. give it more chance + Thread.sleep(100); + } + // hmm? + fail(); } @Test From 0f45d03c51975eac7c96731537a1cffc78cf6dcc Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Tue, 1 Dec 2015 16:01:01 +0100 Subject: [PATCH 066/390] Reworked this change a bit. - GHApiInfo need not be public because it's not publicly exposed. - Throwing an exception is better IMO as it allows richer error message, including the differentiation between unreachable host name vs wrong URL, and reporting the API endpoint URL that was actually tried. --- .../java/org/kohsuke/github/GHApiInfo.java | 14 --------- src/main/java/org/kohsuke/github/GitHub.java | 30 +++++++++++-------- .../java/org/kohsuke/github/GitHubTest.java | 2 +- 3 files changed, 19 insertions(+), 27 deletions(-) delete mode 100644 src/main/java/org/kohsuke/github/GHApiInfo.java diff --git a/src/main/java/org/kohsuke/github/GHApiInfo.java b/src/main/java/org/kohsuke/github/GHApiInfo.java deleted file mode 100644 index 131e0de647..0000000000 --- a/src/main/java/org/kohsuke/github/GHApiInfo.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.kohsuke.github; - -/** - * Represents information about Github API. - */ -public class GHApiInfo { - - private String rate_limit_url; - - public String getRateLimitUrl() { - return rate_limit_url; - } - -} diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 1ca5ed968e..6b434fe2a5 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -455,21 +455,27 @@ public boolean isCredentialValid() throws IOException { } } + private static class GHApiInfo { + private String rate_limit_url; + + void check(String apiUrl) throws IOException { + if (rate_limit_url==null) + throw new IOException(apiUrl+" doesn't look like GitHub API URL"); + + // make sure that the URL is legitimate + new URL(rate_limit_url); + } + } + /** * Ensures that the API URL is valid. + * + *

+ * This method returns normally if the endpoint is reachable and verified to be GitHub API URL. + * Otherwise this method throws {@link IOException} to indicate the problem. */ - public boolean isApiUrlValid() throws IOException { - try { - GHApiInfo apiInfo = retrieve().to("/", GHApiInfo.class); - try { - new URL(apiInfo.getRateLimitUrl()); - return true; - } catch (MalformedURLException mue) { - return false; - } - } catch (IOException e) { - return false; - } + public void checkApiUrlValidity() throws IOException { + retrieve().to("/", GHApiInfo.class).check(apiUrl); } /** diff --git a/src/test/java/org/kohsuke/github/GitHubTest.java b/src/test/java/org/kohsuke/github/GitHubTest.java index 5c5ee982fe..1663d24144 100644 --- a/src/test/java/org/kohsuke/github/GitHubTest.java +++ b/src/test/java/org/kohsuke/github/GitHubTest.java @@ -124,6 +124,6 @@ public void testGitHubEnterpriseDoesNotHaveRateLimit() throws IOException { @Test public void testGitHubIsApiUrlValid() throws IOException { GitHub github = GitHub.connectAnonymously(); - assertTrue(github.isApiUrlValid()); + github.checkApiUrlValidity(); } } From e33bdd7e62663756ebb76796c141ff806d495070 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Tue, 1 Dec 2015 16:17:03 +0100 Subject: [PATCH 067/390] Two teams now. I assume this is because 'owner' is now a team. --- src/test/java/org/kohsuke/github/AppTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/org/kohsuke/github/AppTest.java b/src/test/java/org/kohsuke/github/AppTest.java index d2b68e112c..5d5e0a5fef 100755 --- a/src/test/java/org/kohsuke/github/AppTest.java +++ b/src/test/java/org/kohsuke/github/AppTest.java @@ -286,7 +286,8 @@ public void testOrgFork() throws Exception { @Test public void testGetTeamsForRepo() throws Exception { kohsuke(); - assertEquals(1, gitHub.getOrganization("github-api-test-org").getRepository("testGetTeamsForRepo").getTeams().size()); + // 'Core Developers' and 'Owners' + assertEquals(2, gitHub.getOrganization("github-api-test-org").getRepository("testGetTeamsForRepo").getTeams().size()); } @Test From c2f2d0f8af83b187417bce9cee776086a9c323c6 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Tue, 1 Dec 2015 16:23:51 +0100 Subject: [PATCH 068/390] Making FindBugs happy --- .../org/kohsuke/github/extras/ImpatientHttpConnector.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/org/kohsuke/github/extras/ImpatientHttpConnector.java b/src/main/java/org/kohsuke/github/extras/ImpatientHttpConnector.java index e0e18fc962..740b9a037d 100644 --- a/src/main/java/org/kohsuke/github/extras/ImpatientHttpConnector.java +++ b/src/main/java/org/kohsuke/github/extras/ImpatientHttpConnector.java @@ -1,5 +1,6 @@ package org.kohsuke.github.extras; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.kohsuke.github.HttpConnector; import java.io.IOException; @@ -46,9 +47,12 @@ public HttpURLConnection connect(URL url) throws IOException { /** * Default connection timeout in milliseconds */ + @SuppressFBWarnings("MS_SHOULD_BE_FINAL") public static int CONNECT_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(10); + /** * Default read timeout in milliseconds */ + @SuppressFBWarnings("MS_SHOULD_BE_FINAL") public static int READ_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(10); } From b24fcb18af6bd3f00302371cafd0335de7c756e6 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Tue, 1 Dec 2015 16:27:24 +0100 Subject: [PATCH 069/390] [maven-release-plugin] prepare release github-api-1.71 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 02b788b6a4..4847f4885c 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.71-SNAPSHOT + 1.71 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - HEAD + github-api-1.71 From 90d8e65a3b5f5e09645dd75b2a9408a6f31e5727 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Tue, 1 Dec 2015 16:27:29 +0100 Subject: [PATCH 070/390] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 4847f4885c..0157b91a59 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.71 + 1.72-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - github-api-1.71 + HEAD From ed8cd0ad19189314d8d43add511ed251dc68e032 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Tue, 1 Dec 2015 17:02:53 +0100 Subject: [PATCH 071/390] Added getter for ID And the actual value has already gone past 'int' This fixes issue #199 --- src/main/java/org/kohsuke/github/GHEventInfo.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHEventInfo.java b/src/main/java/org/kohsuke/github/GHEventInfo.java index 9772cba16e..0268924ea2 100644 --- a/src/main/java/org/kohsuke/github/GHEventInfo.java +++ b/src/main/java/org/kohsuke/github/GHEventInfo.java @@ -18,6 +18,7 @@ public class GHEventInfo { // we don't want to expose Jackson dependency to the user. This needs databinding private ObjectNode payload; + private long id; private String created_at; private String type; @@ -54,6 +55,10 @@ public GHEvent getType() { return this; } + public long getId() { + return id; + } + public Date getCreatedAt() { return GitHub.parseDate(created_at); } From 8cb70948034db5efb068b19f72199571afa34716 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 2 Dec 2015 08:35:56 +0100 Subject: [PATCH 072/390] Added pagination for following & follower --- src/main/java/org/kohsuke/github/GHUser.java | 32 ++++++++++++++++--- .../java/org/kohsuke/github/UserTest.java | 30 +++++++++++++++++ 2 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 src/test/java/org/kohsuke/github/UserTest.java diff --git a/src/main/java/org/kohsuke/github/GHUser.java b/src/main/java/org/kohsuke/github/GHUser.java index 2242f4a6e4..a3202c95cc 100644 --- a/src/main/java/org/kohsuke/github/GHUser.java +++ b/src/main/java/org/kohsuke/github/GHUser.java @@ -56,8 +56,14 @@ public void unfollow() throws IOException { */ @WithBridgeMethods(Set.class) public GHPersonSet getFollows() throws IOException { - GHUser[] followers = root.retrieve().to("/users/" + login + "/following", GHUser[].class); - return new GHPersonSet(Arrays.asList(wrap(followers,root))); + return new GHPersonSet(listFollows().asList()); + } + + /** + * Lists the users that this user is following + */ + public PagedIterable listFollows() { + return listUser("following"); } /** @@ -65,8 +71,26 @@ public GHPersonSet getFollows() throws IOException { */ @WithBridgeMethods(Set.class) public GHPersonSet getFollowers() throws IOException { - GHUser[] followers = root.retrieve().to("/users/" + login + "/followers", GHUser[].class); - return new GHPersonSet(Arrays.asList(wrap(followers,root))); + return new GHPersonSet(listFollowers().asList()); + } + + /** + * Lists the users who are following this user. + */ + public PagedIterable listFollowers() { + return listUser("followers"); + } + + private PagedIterable listUser(final String suffix) { + return new PagedIterable() { + public PagedIterator iterator() { + return new PagedIterator(root.retrieve().asIterator(getApiTailUrl(suffix), GHUser[].class)) { + protected void wrapUp(GHUser[] page) { + GHUser.wrap(page,root); + } + }; + } + }; } /** diff --git a/src/test/java/org/kohsuke/github/UserTest.java b/src/test/java/org/kohsuke/github/UserTest.java new file mode 100644 index 0000000000..d35632fda2 --- /dev/null +++ b/src/test/java/org/kohsuke/github/UserTest.java @@ -0,0 +1,30 @@ +package org.kohsuke.github; + +import org.junit.Test; + +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; + +/** + * @author Kohsuke Kawaguchi + */ +public class UserTest extends AbstractGitHubApiTestBase { + @Test + public void listFollowsAndFollowers() throws IOException { + GHUser u = gitHub.getUser("rtyler"); + assertNotEquals( + count50(u.listFollowers()), + count50(u.listFollows())); + } + + private Set count50(PagedIterable l) { + Set users = new HashSet(); + PagedIterator itr = l.iterator(); + for (int i=0; i<50 && itr.hasNext(); i++) { + users.add(itr.next()); + } + assertEquals(50, users.size()); + return users; + } +} From 83ffe75baaf2b61ba41ee8bacf93264690c07cab Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 2 Dec 2015 12:03:39 +0100 Subject: [PATCH 073/390] Fixed rate handling limit handling Issue #220. If RateLimitHandler returns normally, it should retry. --- src/main/java/org/kohsuke/github/Requester.java | 1 + src/test/java/Foo.java | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index 81fe507d8b..b1e750ff74 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -501,6 +501,7 @@ private InputStream wrapStream(InputStream in) throws IOException { if ("0".equals(uc.getHeaderField("X-RateLimit-Remaining"))) { root.rateLimitHandler.onError(e,uc); + return; } InputStream es = wrapStream(uc.getErrorStream()); diff --git a/src/test/java/Foo.java b/src/test/java/Foo.java index 5df13995c5..a29baac4b4 100644 --- a/src/test/java/Foo.java +++ b/src/test/java/Foo.java @@ -1,4 +1,5 @@ import org.kohsuke.github.GHRepository; +import org.kohsuke.github.GHUser; import org.kohsuke.github.GitHub; import java.util.Collection; @@ -14,4 +15,11 @@ public static void main(String[] args) throws Exception { } System.out.println(lst.size()); } + + private static void testRateLimit() throws Exception { + GitHub g = GitHub.connectAnonymously(); + for (GHUser u : g.getOrganization("jenkinsci").listMembers()) { + u.getFollowersCount(); + } + } } From 841f77bac28d28aa73ceee22f45df8ac7fa88f92 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Thu, 3 Dec 2015 16:33:39 +0100 Subject: [PATCH 074/390] Naming anonymous iterator. ... in anticipation of the page size support. --- .../java/org/kohsuke/github/Requester.java | 153 +++++++++--------- 1 file changed, 78 insertions(+), 75 deletions(-) diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index b1e750ff74..14ebe5f3bb 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -42,13 +42,11 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; -import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.GZIPInputStream; @@ -330,104 +328,109 @@ private boolean isMethodWithBody() { * * Every iterator call reports a new batch. */ - /*package*/ Iterator asIterator(final String _tailApiUrl, final Class type) { + /*package*/ PagingIterator asIterator(String tailApiUrl, Class type) { method("GET"); - final StringBuilder strBuilder = new StringBuilder(_tailApiUrl); + StringBuilder s = new StringBuilder(tailApiUrl); if (!args.isEmpty()) { - boolean first=true; + boolean first = true; try { for (Entry a : args) { - strBuilder.append(first ? '?' : '&'); + s.append(first ? '?' : '&'); first = false; - strBuilder.append(URLEncoder.encode(a.key, "UTF-8")); - strBuilder.append('='); - strBuilder.append(URLEncoder.encode(a.value.toString(), "UTF-8")); + s.append(URLEncoder.encode(a.key, "UTF-8")); + s.append('='); + s.append(URLEncoder.encode(a.value.toString(), "UTF-8")); } } catch (UnsupportedEncodingException e) { throw new AssertionError(e); // UTF-8 is mandatory } } - final String tailApiUrl = strBuilder.toString(); + try { + return new PagingIterator(type, root.getApiURL(s.toString())); + } catch (IOException e) { + throw new Error(e); + } + } - return new Iterator() { - /** - * The next batch to be returned from {@link #next()}. - */ - T next; - /** - * URL of the next resource to be retrieved, or null if no more data is available. - */ - URL url; + class PagingIterator implements Iterator { - { - try { - url = root.getApiURL(tailApiUrl); - } catch (IOException e) { - throw new Error(e); - } - } + private final Class type; - public boolean hasNext() { - fetch(); - return next!=null; - } + /** + * The next batch to be returned from {@link #next()}. + */ + private T next; - public T next() { - fetch(); - T r = next; - if (r==null) throw new NoSuchElementException(); - next = null; - return r; - } + /** + * URL of the next resource to be retrieved, or null if no more data is available. + */ + private URL url; - public void remove() { - throw new UnsupportedOperationException(); - } + PagingIterator(Class type, URL url) { + this.url = url; + this.type = type; + } - private void fetch() { - if (next!=null) return; // already fetched - if (url==null) return; // no more data to fetch + public boolean hasNext() { + fetch(); + return next!=null; + } - try { - while (true) {// loop while API rate limit is hit - setupConnection(url); - try { - next = parse(type,null); - assert next!=null; - findNextURL(); - return; - } catch (IOException e) { - handleApiError(e); - } - } - } catch (IOException e) { - throw new Error(e); - } - } + public T next() { + fetch(); + T r = next; + if (r==null) throw new NoSuchElementException(); + next = null; + return r; + } - /** - * Locate the next page from the pagination "Link" tag. - */ - private void findNextURL() throws MalformedURLException { - url = null; // start defensively - String link = uc.getHeaderField("Link"); - if (link==null) return; - - for (String token : link.split(", ")) { - if (token.endsWith("rel=\"next\"")) { - // found the next page. This should look something like - // ; rel="next" - int idx = token.indexOf('>'); - url = new URL(token.substring(1,idx)); + public void remove() { + throw new UnsupportedOperationException(); + } + + private void fetch() { + if (next!=null) return; // already fetched + if (url==null) return; // no more data to fetch + + try { + while (true) {// loop while API rate limit is hit + setupConnection(url); + try { + next = parse(type,null); + assert next!=null; + findNextURL(); return; + } catch (IOException e) { + handleApiError(e); } } + } catch (IOException e) { + throw new Error(e); + } + } - // no more "next" link. we are done. + /** + * Locate the next page from the pagination "Link" tag. + */ + private void findNextURL() throws MalformedURLException { + url = null; // start defensively + String link = uc.getHeaderField("Link"); + if (link==null) return; + + for (String token : link.split(", ")) { + if (token.endsWith("rel=\"next\"")) { + // found the next page. This should look something like + // ; rel="next" + int idx = token.indexOf('>'); + url = new URL(token.substring(1,idx)); + return; + } } - }; + + // no more "next" link. we are done. + } } From dbddf5b9eb500221a4c6be1e523a138de74261c4 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Thu, 3 Dec 2015 17:41:43 +0100 Subject: [PATCH 075/390] Implemented pagenation size support. --- .../java/org/kohsuke/github/GHCommit.java | 4 +- .../kohsuke/github/GHCommitQueryBuilder.java | 4 +- .../java/org/kohsuke/github/GHContent.java | 4 +- src/main/java/org/kohsuke/github/GHGist.java | 4 +- src/main/java/org/kohsuke/github/GHIssue.java | 4 +- .../java/org/kohsuke/github/GHMyself.java | 4 +- .../org/kohsuke/github/GHOrganization.java | 16 ++--- .../java/org/kohsuke/github/GHPerson.java | 6 +- .../org/kohsuke/github/GHPullRequest.java | 12 ++-- .../java/org/kohsuke/github/GHRepository.java | 65 +++++++++---------- .../org/kohsuke/github/GHSearchBuilder.java | 4 +- src/main/java/org/kohsuke/github/GHTeam.java | 8 +-- src/main/java/org/kohsuke/github/GHUser.java | 17 +++-- src/main/java/org/kohsuke/github/GitHub.java | 4 +- .../org/kohsuke/github/PagedIterable.java | 22 ++++++- .../java/org/kohsuke/github/Requester.java | 5 +- .../kohsuke/github/RepositoryMockTest.java | 2 +- 17 files changed, 103 insertions(+), 82 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHCommit.java b/src/main/java/org/kohsuke/github/GHCommit.java index b45683f2d2..2b68ff9a95 100644 --- a/src/main/java/org/kohsuke/github/GHCommit.java +++ b/src/main/java/org/kohsuke/github/GHCommit.java @@ -273,8 +273,8 @@ private GHUser resolveUser(User author) throws IOException { */ public PagedIterable listComments() { return new PagedIterable() { - public PagedIterator iterator() { - return new PagedIterator(owner.root.retrieve().asIterator(String.format("/repos/%s/%s/commits/%s/comments", owner.getOwnerName(), owner.getName(), sha), GHCommitComment[].class)) { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(owner.root.retrieve().asIterator(String.format("/repos/%s/%s/commits/%s/comments", owner.getOwnerName(), owner.getName(), sha), GHCommitComment[].class, pageSize)) { @Override protected void wrapUp(GHCommitComment[] page) { for (GHCommitComment c : page) diff --git a/src/main/java/org/kohsuke/github/GHCommitQueryBuilder.java b/src/main/java/org/kohsuke/github/GHCommitQueryBuilder.java index 6d0a7ae995..bac8c89ee6 100644 --- a/src/main/java/org/kohsuke/github/GHCommitQueryBuilder.java +++ b/src/main/java/org/kohsuke/github/GHCommitQueryBuilder.java @@ -92,8 +92,8 @@ public GHCommitQueryBuilder until(long timestamp) { */ public PagedIterable list() { return new PagedIterable() { - public PagedIterator iterator() { - return new PagedIterator(req.asIterator(repo.getApiTailUrl("commits"), GHCommit[].class)) { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(req.asIterator(repo.getApiTailUrl("commits"), GHCommit[].class, pageSize)) { protected void wrapUp(GHCommit[] page) { for (GHCommit c : page) c.wrapUp(repo); diff --git a/src/main/java/org/kohsuke/github/GHContent.java b/src/main/java/org/kohsuke/github/GHContent.java index c79e00e384..8955505219 100644 --- a/src/main/java/org/kohsuke/github/GHContent.java +++ b/src/main/java/org/kohsuke/github/GHContent.java @@ -152,8 +152,8 @@ public PagedIterable listDirectoryContent() throws IOException { throw new IllegalStateException(path+" is not a directory"); return new PagedIterable() { - public PagedIterator iterator() { - return new PagedIterator(root.retrieve().asIterator(url, GHContent[].class)) { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator(url, GHContent[].class, pageSize)) { @Override protected void wrapUp(GHContent[] page) { GHContent.wrap(page, repository); diff --git a/src/main/java/org/kohsuke/github/GHGist.java b/src/main/java/org/kohsuke/github/GHGist.java index f608af3da6..eb105b40c6 100644 --- a/src/main/java/org/kohsuke/github/GHGist.java +++ b/src/main/java/org/kohsuke/github/GHGist.java @@ -140,8 +140,8 @@ public GHGist fork() throws IOException { public PagedIterable listForks() { return new PagedIterable() { - public PagedIterator iterator() { - return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("forks"), GHGist[].class)) { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("forks"), GHGist[].class, pageSize)) { @Override protected void wrapUp(GHGist[] page) { try { diff --git a/src/main/java/org/kohsuke/github/GHIssue.java b/src/main/java/org/kohsuke/github/GHIssue.java index d45e49b935..39e5c24b70 100644 --- a/src/main/java/org/kohsuke/github/GHIssue.java +++ b/src/main/java/org/kohsuke/github/GHIssue.java @@ -205,8 +205,8 @@ public List getComments() throws IOException { */ public PagedIterable listComments() throws IOException { return new PagedIterable() { - public PagedIterator iterator() { - return new PagedIterator(root.retrieve().asIterator(getIssuesApiRoute() + "/comments", GHIssueComment[].class)) { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator(getIssuesApiRoute() + "/comments", GHIssueComment[].class, pageSize)) { protected void wrapUp(GHIssueComment[] page) { for (GHIssueComment c : page) c.wrapUp(GHIssue.this); diff --git a/src/main/java/org/kohsuke/github/GHMyself.java b/src/main/java/org/kohsuke/github/GHMyself.java index 74ba96189d..c473af4806 100644 --- a/src/main/java/org/kohsuke/github/GHMyself.java +++ b/src/main/java/org/kohsuke/github/GHMyself.java @@ -158,9 +158,9 @@ public PagedIterable listRepositories(final int pageSize) { */ public PagedIterable listRepositories(final int pageSize, final RepositoryListFilter repoType) { return new PagedIterable() { - public PagedIterator iterator() { + public PagedIterator _iterator(int pageSize) { return new PagedIterator(root.retrieve().asIterator("/user/repos?per_page=" + pageSize + - "&type=" + repoType.name().toLowerCase(Locale.ENGLISH), GHRepository[].class)) { + "&type=" + repoType.name().toLowerCase(Locale.ENGLISH), GHRepository[].class, pageSize)) { @Override protected void wrapUp(GHRepository[] page) { for (GHRepository c : page) diff --git a/src/main/java/org/kohsuke/github/GHOrganization.java b/src/main/java/org/kohsuke/github/GHOrganization.java index b39cc6b98b..2f4a6c0f4f 100644 --- a/src/main/java/org/kohsuke/github/GHOrganization.java +++ b/src/main/java/org/kohsuke/github/GHOrganization.java @@ -57,8 +57,8 @@ public Map getTeams() throws IOException { */ public PagedIterable listTeams() throws IOException { return new PagedIterable() { - public PagedIterator iterator() { - return new PagedIterator(root.retrieve().asIterator(String.format("/orgs/%s/teams", login), GHTeam[].class)) { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator(String.format("/orgs/%s/teams", login), GHTeam[].class, pageSize)) { @Override protected void wrapUp(GHTeam[] page) { for (GHTeam c : page) @@ -150,9 +150,9 @@ public PagedIterable listMembersWithFilter(String filter) throws IOExcep private PagedIterable listMembers(final String suffix, final String filter) throws IOException { return new PagedIterable() { - public PagedIterator iterator() { + public PagedIterator _iterator(int pageSize) { String filterParams = (filter == null) ? "" : ("?filter=" + filter); - return new PagedIterator(root.retrieve().asIterator(String.format("/orgs/%s/%s%s", login, suffix, filterParams), GHUser[].class)) { + return new PagedIterator(root.retrieve().asIterator(String.format("/orgs/%s/%s%s", login, suffix, filterParams), GHUser[].class, pageSize)) { @Override protected void wrapUp(GHUser[] users) { GHUser.wrap(users, root); @@ -222,8 +222,8 @@ public List getPullRequests() throws IOException { */ public PagedIterable listEvents() throws IOException { return new PagedIterable() { - public PagedIterator iterator() { - return new PagedIterator(root.retrieve().asIterator(String.format("/orgs/%s/events", login), GHEventInfo[].class)) { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator(String.format("/orgs/%s/events", login), GHEventInfo[].class, pageSize)) { @Override protected void wrapUp(GHEventInfo[] page) { for (GHEventInfo c : page) @@ -244,8 +244,8 @@ protected void wrapUp(GHEventInfo[] page) { @Override public PagedIterable listRepositories(final int pageSize) { return new PagedIterable() { - public PagedIterator iterator() { - return new PagedIterator(root.retrieve().asIterator("/orgs/" + login + "/repos?per_page=" + pageSize, GHRepository[].class)) { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator("/orgs/" + login + "/repos?per_page=" + pageSize, GHRepository[].class, pageSize)) { @Override protected void wrapUp(GHRepository[] page) { for (GHRepository c : page) diff --git a/src/main/java/org/kohsuke/github/GHPerson.java b/src/main/java/org/kohsuke/github/GHPerson.java index 1a9a0f1575..e9a750f2cc 100644 --- a/src/main/java/org/kohsuke/github/GHPerson.java +++ b/src/main/java/org/kohsuke/github/GHPerson.java @@ -76,8 +76,8 @@ public PagedIterable listRepositories() { */ public PagedIterable listRepositories(final int pageSize) { return new PagedIterable() { - public PagedIterator iterator() { - return new PagedIterator(root.retrieve().asIterator("/users/" + login + "/repos?per_page=" + pageSize, GHRepository[].class)) { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator("/users/" + login + "/repos?per_page=" + pageSize, GHRepository[].class, pageSize)) { @Override protected void wrapUp(GHRepository[] page) { for (GHRepository c : page) @@ -104,7 +104,7 @@ protected void wrapUp(GHRepository[] page) { public synchronized Iterable> iterateRepositories(final int pageSize) { return new Iterable>() { public Iterator> iterator() { - final Iterator pager = root.retrieve().asIterator("/users/" + login + "/repos?per_page="+pageSize,GHRepository[].class); + final Iterator pager = root.retrieve().asIterator("/users/" + login + "/repos?per_page="+pageSize,GHRepository[].class, pageSize); return new Iterator>() { public boolean hasNext() { diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index 5604d2355e..dd3d93b758 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -210,9 +210,9 @@ private void populate() throws IOException { */ public PagedIterable listFiles() { return new PagedIterable() { - public PagedIterator iterator() { + public PagedIterator _iterator(int pageSize) { return new PagedIterator(root.retrieve().asIterator(String.format("%s/files", getApiURL()), - GHPullRequestFileDetail[].class)) { + GHPullRequestFileDetail[].class, pageSize)) { @Override protected void wrapUp(GHPullRequestFileDetail[] page) { } @@ -226,9 +226,9 @@ protected void wrapUp(GHPullRequestFileDetail[] page) { */ public PagedIterable listReviewComments() throws IOException { return new PagedIterable() { - public PagedIterator iterator() { + public PagedIterator _iterator(int pageSize) { return new PagedIterator(root.retrieve().asIterator(getApiRoute() + "/comments", - GHPullRequestReviewComment[].class)) { + GHPullRequestReviewComment[].class, pageSize)) { protected void wrapUp(GHPullRequestReviewComment[] page) { for (GHPullRequestReviewComment c : page) c.wrapUp(GHPullRequest.this); @@ -243,10 +243,10 @@ protected void wrapUp(GHPullRequestReviewComment[] page) { */ public PagedIterable listCommits() { return new PagedIterable() { - public PagedIterator iterator() { + public PagedIterator _iterator(int pageSize) { return new PagedIterator(root.retrieve().asIterator( String.format("%s/commits", getApiURL()), - GHPullRequestCommitDetail[].class)) { + GHPullRequestCommitDetail[].class, pageSize)) { @Override protected void wrapUp(GHPullRequestCommitDetail[] page) { for (GHPullRequestCommitDetail c : page) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 917be54d7f..6300785ad1 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -36,7 +36,6 @@ 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; @@ -76,8 +75,8 @@ public GHDeploymentBuilder createDeployment(String ref) { public PagedIterable getDeploymentStatuses(final int id) { return new PagedIterable() { - public PagedIterator iterator() { - return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("deployments")+"/"+id+"/statuses", GHDeploymentStatus[].class)) { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("deployments")+"/"+id+"/statuses", GHDeploymentStatus[].class, pageSize)) { @Override protected void wrapUp(GHDeploymentStatus[] page) { for (GHDeploymentStatus c : page) @@ -92,8 +91,8 @@ public PagedIterable listDeployments(String sha,String ref,String List params = Arrays.asList(getParam("sha", sha), getParam("ref", ref), getParam("task", task), getParam("environment", environment)); final String deploymentsUrl = getApiTailUrl("deployments") + "?"+ join(params,"&"); return new PagedIterable() { - public PagedIterator iterator() { - return new PagedIterator(root.retrieve().asIterator(deploymentsUrl, GHDeployment[].class)) { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator(deploymentsUrl, GHDeployment[].class, pageSize)) { @Override protected void wrapUp(GHDeployment[] page) { for (GHDeployment c : page) @@ -241,8 +240,8 @@ public List getIssues(GHIssueState state, GHMilestone milestone) throws */ public PagedIterable listIssues(final GHIssueState state) { return new PagedIterable() { - public PagedIterator iterator() { - return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("issues?state="+state.toString().toLowerCase(Locale.ENGLISH)), GHIssue[].class)) { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("issues?state="+state.toString().toLowerCase(Locale.ENGLISH)), GHIssue[].class, pageSize)) { @Override protected void wrapUp(GHIssue[] page) { for (GHIssue c : page) @@ -281,8 +280,8 @@ public List getReleases() throws IOException { public PagedIterable listReleases() throws IOException { return new PagedIterable() { - public PagedIterator iterator() { - return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("releases"), GHRelease[].class)) { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("releases"), GHRelease[].class, pageSize)) { @Override protected void wrapUp(GHRelease[] page) { for (GHRelease c : page) @@ -295,8 +294,8 @@ protected void wrapUp(GHRelease[] page) { public PagedIterable listTags() throws IOException { return new PagedIterable() { - public PagedIterator iterator() { - return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("tags"), GHTag[].class)) { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("tags"), GHTag[].class, pageSize)) { @Override protected void wrapUp(GHTag[] page) { for (GHTag c : page) @@ -416,9 +415,9 @@ public GHPersonSet getCollaborators() throws IOException { */ public PagedIterable listCollaborators() throws IOException { return new PagedIterable() { - public PagedIterator iterator() { + public PagedIterator _iterator(int pageSize) { - return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("collaborators"), GHUser[].class)) { + return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("collaborators"), GHUser[].class, pageSize)) { @Override protected void wrapUp(GHUser[] users) { @@ -556,12 +555,12 @@ public PagedIterable listForks() { */ public PagedIterable listForks(final ForkSort sort) { return new PagedIterable() { - public PagedIterator iterator() { + public PagedIterator _iterator(int pageSize) { String sortParam = ""; if (sort != null) { sortParam = "?sort=" + sort.toString().toLowerCase(Locale.ENGLISH); } - return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("forks" + sortParam), GHRepository[].class)) { + return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("forks" + sortParam), GHRepository[].class, pageSize)) { @Override protected void wrapUp(GHRepository[] page) { for (GHRepository c : page) { @@ -626,8 +625,8 @@ public List getPullRequests(GHIssueState state) throws IOExceptio */ public PagedIterable listPullRequests(final GHIssueState state) { return new PagedIterable() { - public PagedIterator iterator() { - return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("pulls?state="+state.name().toLowerCase(Locale.ENGLISH)), GHPullRequest[].class)) { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("pulls?state="+state.name().toLowerCase(Locale.ENGLISH)), GHPullRequest[].class, pageSize)) { @Override protected void wrapUp(GHPullRequest[] page) { for (GHPullRequest pr : page) @@ -786,8 +785,8 @@ public GHCommit getCommit(String sha1) throws IOException { */ public PagedIterable listCommits() { return new PagedIterable() { - public PagedIterator iterator() { - return new PagedIterator(root.retrieve().asIterator(String.format("/repos/%s/%s/commits", owner.login, name), GHCommit[].class)) { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator(String.format("/repos/%s/%s/commits", owner.login, name), GHCommit[].class, pageSize)) { protected void wrapUp(GHCommit[] page) { for (GHCommit c : page) c.wrapUp(GHRepository.this); @@ -809,8 +808,8 @@ public GHCommitQueryBuilder queryCommits() { */ public PagedIterable listCommitComments() { return new PagedIterable() { - public PagedIterator iterator() { - return new PagedIterator(root.retrieve().asIterator(String.format("/repos/%s/%s/comments", owner.login, name), GHCommitComment[].class)) { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator(String.format("/repos/%s/%s/comments", owner.login, name), GHCommitComment[].class, pageSize)) { @Override protected void wrapUp(GHCommitComment[] page) { for (GHCommitComment c : page) @@ -826,8 +825,8 @@ protected void wrapUp(GHCommitComment[] page) { */ public PagedIterable listCommitStatuses(final String sha1) throws IOException { return new PagedIterable() { - public PagedIterator iterator() { - return new PagedIterator(root.retrieve().asIterator(String.format("/repos/%s/%s/statuses/%s", owner.login, name, sha1), GHCommitStatus[].class)) { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator(String.format("/repos/%s/%s/statuses/%s", owner.login, name, sha1), GHCommitStatus[].class, pageSize)) { @Override protected void wrapUp(GHCommitStatus[] page) { for (GHCommitStatus c : page) @@ -877,8 +876,8 @@ public GHCommitStatus createCommitStatus(String sha1, GHCommitState state, Strin */ public PagedIterable listEvents() throws IOException { return new PagedIterable() { - public PagedIterator iterator() { - return new PagedIterator(root.retrieve().asIterator(String.format("/repos/%s/%s/events", owner.login, name), GHEventInfo[].class)) { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator(String.format("/repos/%s/%s/events", owner.login, name), GHEventInfo[].class, pageSize)) { @Override protected void wrapUp(GHEventInfo[] page) { for (GHEventInfo c : page) @@ -896,8 +895,8 @@ protected void wrapUp(GHEventInfo[] page) { */ public PagedIterable listLabels() throws IOException { return new PagedIterable() { - public PagedIterator iterator() { - return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("labels"), GHLabel[].class)) { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("labels"), GHLabel[].class, pageSize)) { @Override protected void wrapUp(GHLabel[] page) { for (GHLabel c : page) @@ -926,8 +925,8 @@ public GHLabel createLabel(String name, String color) throws IOException { */ public PagedIterable listSubscribers() { return new PagedIterable() { - public PagedIterator iterator() { - return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("subscribers"), GHUser[].class)) { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("subscribers"), GHUser[].class, pageSize)) { protected void wrapUp(GHUser[] page) { for (GHUser c : page) c.wrapUp(root); @@ -1078,8 +1077,8 @@ public Map getMilestones() throws IOException { */ public PagedIterable listMilestones(final GHIssueState state) { return new PagedIterable() { - public PagedIterator iterator() { - return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("milestones?state="+state.toString().toLowerCase(Locale.ENGLISH)), GHMilestone[].class)) { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("milestones?state="+state.toString().toLowerCase(Locale.ENGLISH)), GHMilestone[].class, pageSize)) { @Override protected void wrapUp(GHMilestone[] page) { for (GHMilestone c : page) @@ -1251,8 +1250,8 @@ public GHSubscription getSubscription() throws IOException { public PagedIterable listContributors() throws IOException { return new PagedIterable() { - public PagedIterator iterator() { - return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("contributors"), Contributor[].class)) { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("contributors"), Contributor[].class, pageSize)) { @Override protected void wrapUp(Contributor[] page) { for (Contributor c : page) diff --git a/src/main/java/org/kohsuke/github/GHSearchBuilder.java b/src/main/java/org/kohsuke/github/GHSearchBuilder.java index 766c6a319f..67d10bdb72 100644 --- a/src/main/java/org/kohsuke/github/GHSearchBuilder.java +++ b/src/main/java/org/kohsuke/github/GHSearchBuilder.java @@ -39,9 +39,9 @@ public GHSearchBuilder q(String term) { */ public PagedSearchIterable list() { return new PagedSearchIterable(root) { - public PagedIterator iterator() { + public PagedIterator _iterator(int pageSize) { req.set("q", StringUtils.join(terms, " ")); - return new PagedIterator(adapt(req.asIterator(getApiUrl(), receiverType))) { + return new PagedIterator(adapt(req.asIterator(getApiUrl(), receiverType, pageSize))) { protected void wrapUp(T[] page) { // SearchResult.getItems() should do it } diff --git a/src/main/java/org/kohsuke/github/GHTeam.java b/src/main/java/org/kohsuke/github/GHTeam.java index 7213f327c9..cf7dd1fc91 100644 --- a/src/main/java/org/kohsuke/github/GHTeam.java +++ b/src/main/java/org/kohsuke/github/GHTeam.java @@ -52,8 +52,8 @@ public int getId() { */ public PagedIterable listMembers() throws IOException { return new PagedIterable() { - public PagedIterator iterator() { - return new PagedIterator(org.root.retrieve().asIterator(api("/members"), GHUser[].class)) { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(org.root.retrieve().asIterator(api("/members"), GHUser[].class, pageSize)) { @Override protected void wrapUp(GHUser[] page) { GHUser.wrap(page, org.root); @@ -89,8 +89,8 @@ public Map getRepositories() throws IOException { public PagedIterable listRepositories() { return new PagedIterable() { - public PagedIterator iterator() { - return new PagedIterator(org.root.retrieve().asIterator(api("/repos"), GHRepository[].class)) { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(org.root.retrieve().asIterator(api("/repos"), GHRepository[].class, pageSize)) { @Override protected void wrapUp(GHRepository[] page) { for (GHRepository r : page) diff --git a/src/main/java/org/kohsuke/github/GHUser.java b/src/main/java/org/kohsuke/github/GHUser.java index a3202c95cc..3e29395ebb 100644 --- a/src/main/java/org/kohsuke/github/GHUser.java +++ b/src/main/java/org/kohsuke/github/GHUser.java @@ -26,7 +26,6 @@ import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import java.io.IOException; -import java.util.Arrays; import java.util.HashSet; import java.util.Set; @@ -83,8 +82,8 @@ public PagedIterable listFollowers() { private PagedIterable listUser(final String suffix) { return new PagedIterable() { - public PagedIterator iterator() { - return new PagedIterator(root.retrieve().asIterator(getApiTailUrl(suffix), GHUser[].class)) { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator(getApiTailUrl(suffix), GHUser[].class, pageSize)) { protected void wrapUp(GHUser[] page) { GHUser.wrap(page,root); } @@ -100,8 +99,8 @@ protected void wrapUp(GHUser[] page) { */ public PagedIterable listSubscriptions() { return new PagedIterable() { - public PagedIterator iterator() { - return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("subscriptions"), GHRepository[].class)) { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("subscriptions"), GHRepository[].class, pageSize)) { protected void wrapUp(GHRepository[] page) { for (GHRepository c : page) c.wrap(root); @@ -157,8 +156,8 @@ public GHPersonSet getOrganizations() throws IOException { */ public PagedIterable listEvents() throws IOException { return new PagedIterable() { - public PagedIterator iterator() { - return new PagedIterator(root.retrieve().asIterator(String.format("/users/%s/events", login), GHEventInfo[].class)) { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator(String.format("/users/%s/events", login), GHEventInfo[].class, pageSize)) { @Override protected void wrapUp(GHEventInfo[] page) { for (GHEventInfo c : page) @@ -174,8 +173,8 @@ protected void wrapUp(GHEventInfo[] page) { */ 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)) { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator(String.format("/users/%s/gists", login), GHGist[].class, pageSize)) { @Override protected void wrapUp(GHGist[] page) { for (GHGist c : page) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 2ef822680c..b6ddd6e965 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -526,8 +526,8 @@ public PagedIterable listAllPublicRepositories() { */ public PagedIterable listAllPublicRepositories(final String since) { return new PagedIterable() { - public PagedIterator iterator() { - return new PagedIterator(retrieve().with("since",since).asIterator("/repositories", GHRepository[].class)) { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(retrieve().with("since",since).asIterator("/repositories", GHRepository[].class, pageSize)) { @Override protected void wrapUp(GHRepository[] page) { for (GHRepository c : page) diff --git a/src/main/java/org/kohsuke/github/PagedIterable.java b/src/main/java/org/kohsuke/github/PagedIterable.java index 8085e1ed53..ae26b1abc6 100644 --- a/src/main/java/org/kohsuke/github/PagedIterable.java +++ b/src/main/java/org/kohsuke/github/PagedIterable.java @@ -1,5 +1,6 @@ package org.kohsuke.github; +import java.io.IOException; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; @@ -11,7 +12,26 @@ * @author Kohsuke Kawaguchi */ public abstract class PagedIterable implements Iterable { - public abstract PagedIterator iterator(); + /** + * Page size. 0 is default. + */ + private int size = 0; + + /** + * Sets the pagination size. + * + *

+ * When set to non-zero, each API call will retrieve this many entries. + */ + void setPageSize(int size) throws IOException { + this.size = size; + } + + public final PagedIterator iterator() { + return _iterator(size); + } + + public abstract PagedIterator _iterator(int pageSize); /** * Eagerly walk {@link Iterable} and return the result in a list. diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index 14ebe5f3bb..7c3052a817 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -328,9 +328,12 @@ private boolean isMethodWithBody() { * * Every iterator call reports a new batch. */ - /*package*/ PagingIterator asIterator(String tailApiUrl, Class type) { + /*package*/ Iterator asIterator(String tailApiUrl, Class type, int pageSize) { method("GET"); + if (pageSize!=0) + args.add(new Entry("per_page",pageSize)); + StringBuilder s = new StringBuilder(tailApiUrl); if (!args.isEmpty()) { boolean first = true; diff --git a/src/test/java/org/kohsuke/github/RepositoryMockTest.java b/src/test/java/org/kohsuke/github/RepositoryMockTest.java index 8c12ed640a..2ff984ef2c 100644 --- a/src/test/java/org/kohsuke/github/RepositoryMockTest.java +++ b/src/test/java/org/kohsuke/github/RepositoryMockTest.java @@ -48,7 +48,7 @@ public void listCollaborators() throws Exception { when(requester.asIterator("/repos/*/*/collaborators", - GHUser[].class)).thenReturn(iterator, iterator); + GHUser[].class, 0)).thenReturn(iterator, iterator); PagedIterable pagedIterable = Mockito.mock(PagedIterable.class); From 2603b5a402a3f0669f5828c316c4d589cf1d1e1b Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Thu, 3 Dec 2015 17:55:06 +0100 Subject: [PATCH 076/390] Added stargazers and stars --- .../java/org/kohsuke/github/GHRepository.java | 19 +++++++++++++++---- src/main/java/org/kohsuke/github/GHUser.java | 13 ++++++++++++- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 6300785ad1..dbc6a836e8 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -714,7 +714,7 @@ public GHCompare getCompare(GHBranch id1, GHBranch id2) throws IOException { * @throws IOException on failure communicating with GitHub */ public GHRef[] getRefs() throws IOException { - return GHRef.wrap(root.retrieve().to(String.format("/repos/%s/%s/git/refs", owner.login, name), GHRef[].class),root); + return GHRef.wrap(root.retrieve().to(String.format("/repos/%s/%s/git/refs", owner.login, name), GHRef[].class), root); } /** @@ -868,7 +868,7 @@ public GHCommitStatus createCommitStatus(String sha1, GHCommitState state, Strin * @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); } /** @@ -914,7 +914,7 @@ public GHLabel getLabel(String name) throws IOException { public GHLabel createLabel(String name, String color) throws IOException { return root.retrieve().method("POST") .with("name",name) - .with("color",color) + .with("color", color) .to(getApiTailUrl("labels"), GHLabel.class).wrapUp(this); } @@ -924,9 +924,20 @@ public GHLabel createLabel(String name, String color) throws IOException { * https://developer.github.com/v3/activity/watching/ */ public PagedIterable listSubscribers() { + return listUsers("subscribers"); + } + + /** + * Lists all the users who have starred this repo. + */ + public PagedIterable listStargazers() { + return listUsers("stargazers"); + } + + private PagedIterable listUsers(final String suffix) { return new PagedIterable() { public PagedIterator _iterator(int pageSize) { - return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("subscribers"), GHUser[].class, pageSize)) { + return new PagedIterator(root.retrieve().asIterator(getApiTailUrl(suffix), GHUser[].class, pageSize)) { protected void wrapUp(GHUser[] page) { for (GHUser c : page) c.wrapUp(root); diff --git a/src/main/java/org/kohsuke/github/GHUser.java b/src/main/java/org/kohsuke/github/GHUser.java index 3e29395ebb..319908cbae 100644 --- a/src/main/java/org/kohsuke/github/GHUser.java +++ b/src/main/java/org/kohsuke/github/GHUser.java @@ -98,9 +98,20 @@ protected void wrapUp(GHUser[] page) { * https://developer.github.com/v3/activity/watching/ */ public PagedIterable listSubscriptions() { + return listRepositories("subscriptions"); + } + + /** + * Lists all the repositories that this user has starred. + */ + public PagedIterable listStarredRepositories() { + return listRepositories("starred"); + } + + private PagedIterable listRepositories(final String suffix) { return new PagedIterable() { public PagedIterator _iterator(int pageSize) { - return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("subscriptions"), GHRepository[].class, pageSize)) { + return new PagedIterator(root.retrieve().asIterator(getApiTailUrl(suffix), GHRepository[].class, pageSize)) { protected void wrapUp(GHRepository[] page) { for (GHRepository c : page) c.wrap(root); From 9149b6b998acdffab54d805fe22abdc95bf7de7a Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Thu, 10 Dec 2015 05:53:55 -0800 Subject: [PATCH 077/390] GHCommit might be only partially populated. This fixes issue #230 --- .../java/org/kohsuke/github/GHCommit.java | 22 ++++++++++++++----- .../java/org/kohsuke/github/CommitTest.java | 12 ++++++++++ 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHCommit.java b/src/main/java/org/kohsuke/github/GHCommit.java index 2b68ff9a95..a350eeb535 100644 --- a/src/main/java/org/kohsuke/github/GHCommit.java +++ b/src/main/java/org/kohsuke/github/GHCommit.java @@ -192,21 +192,24 @@ public GHRepository getOwner() { /** * Number of lines added + removed. */ - public int getLinesChanged() { + public int getLinesChanged() throws IOException { + populate(); return stats.total; } /** * Number of lines added. */ - public int getLinesAdded() { + public int getLinesAdded() throws IOException { + populate(); return stats.additions; } /** * Number of lines removed. */ - public int getLinesDeleted() { + public int getLinesDeleted() throws IOException { + populate(); return stats.deletions; } @@ -223,7 +226,8 @@ public String getSHA1() { * @return * Can be empty but never null. */ - public List getFiles() { + public List getFiles() throws IOException { + populate(); return files!=null ? Collections.unmodifiableList(files) : Collections.emptyList(); } @@ -301,7 +305,7 @@ public GHCommitComment createComment(String body, String path, Integer line, Int } public GHCommitComment createComment(String body) throws IOException { - return createComment(body,null,null,null); + return createComment(body, null, null, null); } /** @@ -318,6 +322,14 @@ public GHCommitStatus getLastStatus() throws IOException { return owner.getLastCommitStatus(sha); } + /** + * Some of the fields are not always filled in when this object is retrieved as a part of another API call. + */ + void populate() throws IOException { + if (files==null && stats==null) + owner.root.retrieve().to(owner.getApiTailUrl("commits/" + sha), this); + } + GHCommit wrapUp(GHRepository owner) { this.owner = owner; return this; diff --git a/src/test/java/org/kohsuke/github/CommitTest.java b/src/test/java/org/kohsuke/github/CommitTest.java index fff9084ebd..c42fceef41 100644 --- a/src/test/java/org/kohsuke/github/CommitTest.java +++ b/src/test/java/org/kohsuke/github/CommitTest.java @@ -1,5 +1,7 @@ package org.kohsuke.github; +import com.google.common.collect.Iterables; +import com.google.common.collect.Iterators; import org.junit.Test; import java.io.IOException; @@ -13,4 +15,14 @@ public void lastStatus() throws IOException { GHTag t = gitHub.getRepository("stapler/stapler").listTags().iterator().next(); t.getCommit().getLastStatus(); } + + @Test // issue 230 + public void listFiles() throws Exception { + GHRepository repo = gitHub.getRepository("stapler/stapler"); + PagedIterable commits = repo.queryCommits().path("pom.xml").list(); + for (GHCommit commit : Iterables.limit(commits, 10)) { + GHCommit expected = repo.getCommit( commit.getSHA1() ); + assertEquals(expected.getFiles().size(), commit.getFiles().size()); + } + } } From 1bbbcabae010c6d677b0c73d08c11d2b899b5831 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Thu, 10 Dec 2015 05:56:08 -0800 Subject: [PATCH 078/390] Making API flow better --- src/main/java/org/kohsuke/github/PagedIterable.java | 3 ++- src/main/java/org/kohsuke/github/PagedSearchIterable.java | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/PagedIterable.java b/src/main/java/org/kohsuke/github/PagedIterable.java index ae26b1abc6..af6406a8cd 100644 --- a/src/main/java/org/kohsuke/github/PagedIterable.java +++ b/src/main/java/org/kohsuke/github/PagedIterable.java @@ -23,8 +23,9 @@ public abstract class PagedIterable implements Iterable { *

* When set to non-zero, each API call will retrieve this many entries. */ - void setPageSize(int size) throws IOException { + public PagedIterable withPageSize(int size) throws IOException { this.size = size; + return this; } public final PagedIterator iterator() { diff --git a/src/main/java/org/kohsuke/github/PagedSearchIterable.java b/src/main/java/org/kohsuke/github/PagedSearchIterable.java index 222cedcd00..6cd26c3a94 100644 --- a/src/main/java/org/kohsuke/github/PagedSearchIterable.java +++ b/src/main/java/org/kohsuke/github/PagedSearchIterable.java @@ -1,6 +1,8 @@ package org.kohsuke.github; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + +import java.io.IOException; import java.util.Iterator; /** @@ -22,6 +24,11 @@ public abstract class PagedSearchIterable extends PagedIterable { this.root = root; } + @Override + public PagedSearchIterable withPageSize(int size) throws IOException { + return (PagedSearchIterable)super.withPageSize(size); + } + /** * Returns the total number of hit, including the results that's not yet fetched. */ From 03ac6c72e76a587f11fdd2b86be76619a81520ef Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Thu, 10 Dec 2015 06:01:34 -0800 Subject: [PATCH 079/390] Formatting change --- src/main/java/org/kohsuke/github/SearchResult.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/SearchResult.java b/src/main/java/org/kohsuke/github/SearchResult.java index 7b9f9a0c59..2fb2dca06e 100644 --- a/src/main/java/org/kohsuke/github/SearchResult.java +++ b/src/main/java/org/kohsuke/github/SearchResult.java @@ -7,7 +7,6 @@ * * @author Kohsuke Kawaguchi */ - abstract class SearchResult { @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Field comes from JSON deserialization") int total_count; From 2440a676bdb9e880c3752312bb45ff42ff3f8e6a Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Thu, 10 Dec 2015 06:24:51 -0800 Subject: [PATCH 080/390] Added more comprehensive API to list pull requests This fixes issue #234 --- .../java/org/kohsuke/github/GHDirection.java | 10 ++++ .../java/org/kohsuke/github/GHIssueState.java | 6 +- .../github/GHPullRequestQueryBuilder.java | 58 +++++++++++++++++++ .../org/kohsuke/github/GHQueryBuilder.java | 21 +++++++ .../java/org/kohsuke/github/GHRepository.java | 26 ++++----- .../org/kohsuke/github/GHSearchBuilder.java | 10 ++-- .../java/org/kohsuke/github/Requester.java | 9 +++ 7 files changed, 120 insertions(+), 20 deletions(-) create mode 100644 src/main/java/org/kohsuke/github/GHDirection.java create mode 100644 src/main/java/org/kohsuke/github/GHPullRequestQueryBuilder.java create mode 100644 src/main/java/org/kohsuke/github/GHQueryBuilder.java diff --git a/src/main/java/org/kohsuke/github/GHDirection.java b/src/main/java/org/kohsuke/github/GHDirection.java new file mode 100644 index 0000000000..0db172dccf --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHDirection.java @@ -0,0 +1,10 @@ +package org.kohsuke.github; + +/** + * Sort direction + * + * @author Kohsuke Kawaguchi + */ +public enum GHDirection { + ASC, DESC +} diff --git a/src/main/java/org/kohsuke/github/GHIssueState.java b/src/main/java/org/kohsuke/github/GHIssueState.java index d0af550ead..ec3cf10d24 100644 --- a/src/main/java/org/kohsuke/github/GHIssueState.java +++ b/src/main/java/org/kohsuke/github/GHIssueState.java @@ -24,7 +24,11 @@ package org.kohsuke.github; +/** + * @see GHPullRequestQueryBuilder#state(GHIssueState) + */ public enum GHIssueState { OPEN, - CLOSED + CLOSED, + ALL } \ No newline at end of file diff --git a/src/main/java/org/kohsuke/github/GHPullRequestQueryBuilder.java b/src/main/java/org/kohsuke/github/GHPullRequestQueryBuilder.java new file mode 100644 index 0000000000..141cf4d681 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHPullRequestQueryBuilder.java @@ -0,0 +1,58 @@ +package org.kohsuke.github; + +/** + * Lists up pull requests with some filtering and sorting. + * + * @author Kohsuke Kawaguchi + * @see GHRepository#queryPullRequests() + */ +public class GHPullRequestQueryBuilder extends GHQueryBuilder { + private final GHRepository repo; + + /*package*/ GHPullRequestQueryBuilder(GHRepository repo) { + super(repo.root); + this.repo = repo; + } + + public GHPullRequestQueryBuilder state(GHIssueState state) { + req.with("state",state); + return this; + } + + public GHPullRequestQueryBuilder head(String head) { + req.with("head",head); + return this; + } + + public GHPullRequestQueryBuilder base(String base) { + req.with("base",base); + return this; + } + + public GHPullRequestQueryBuilder sort(Sort sort) { + req.with("sort",sort); + return this; + } + + public enum Sort { CREATED, UPDATED, POPULARITY, LONG_RUNNING } + + public GHPullRequestQueryBuilder direction(GHDirection d) { + req.with("direction",d); + return this; + } + + @Override + public PagedIterable list() { + return new PagedIterable() { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(req.asIterator(repo.getApiTailUrl("pulls"), GHPullRequest[].class, pageSize)) { + @Override + protected void wrapUp(GHPullRequest[] page) { + for (GHPullRequest pr : page) + pr.wrapUp(repo); + } + }; + } + }; + } +} diff --git a/src/main/java/org/kohsuke/github/GHQueryBuilder.java b/src/main/java/org/kohsuke/github/GHQueryBuilder.java new file mode 100644 index 0000000000..bb85fbbe95 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHQueryBuilder.java @@ -0,0 +1,21 @@ +package org.kohsuke.github; + +/** + * Used to specify filters, sort order, etc for listing items in a collection. + * + * @author Kohsuke Kawaguchi + */ +public abstract class GHQueryBuilder { + protected final GitHub root; + protected final Requester req; + + /*package*/ GHQueryBuilder(GitHub root) { + this.root = root; + this.req = root.retrieve(); + } + + /** + * Start listing items by using the settings built up on this object. + */ + public abstract PagedIterable list(); +} diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index dbc6a836e8..38a821143a 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -617,24 +617,24 @@ public GHPullRequest getPullRequest(int i) throws IOException { * @see #listPullRequests(GHIssueState) */ public List getPullRequests(GHIssueState state) throws IOException { - return listPullRequests(state).asList(); + return queryPullRequests().state(state).list().asList(); } /** * Retrieves all the pull requests of a particular state. + * + * @deprecated + * Use {@link #queryPullRequests()} */ - public PagedIterable listPullRequests(final GHIssueState state) { - return new PagedIterable() { - public PagedIterator _iterator(int pageSize) { - return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("pulls?state="+state.name().toLowerCase(Locale.ENGLISH)), GHPullRequest[].class, pageSize)) { - @Override - protected void wrapUp(GHPullRequest[] page) { - for (GHPullRequest pr : page) - pr.wrapUp(GHRepository.this); - } - }; - } - }; + public PagedIterable listPullRequests(GHIssueState state) { + return queryPullRequests().state(state).list(); + } + + /** + * Retrieves pull requests. + */ + public GHPullRequestQueryBuilder queryPullRequests() { + return new GHPullRequestQueryBuilder(this); } /** diff --git a/src/main/java/org/kohsuke/github/GHSearchBuilder.java b/src/main/java/org/kohsuke/github/GHSearchBuilder.java index 67d10bdb72..17c2db85b8 100644 --- a/src/main/java/org/kohsuke/github/GHSearchBuilder.java +++ b/src/main/java/org/kohsuke/github/GHSearchBuilder.java @@ -10,9 +10,7 @@ * * @author Kohsuke Kawaguchi */ -public abstract class GHSearchBuilder { - protected final GitHub root; - protected final Requester req; +public abstract class GHSearchBuilder extends GHQueryBuilder { protected final List terms = new ArrayList(); /** @@ -21,15 +19,14 @@ public abstract class GHSearchBuilder { private final Class> receiverType; /*package*/ GHSearchBuilder(GitHub root, Class> receiverType) { - this.root = root; - this.req = root.retrieve(); + super(root); this.receiverType = receiverType; } /** * Search terms. */ - public GHSearchBuilder q(String term) { + public GHQueryBuilder q(String term) { terms.add(term); return this; } @@ -37,6 +34,7 @@ public GHSearchBuilder q(String term) { /** * Performs the search. */ + @Override public PagedSearchIterable list() { return new PagedSearchIterable(root) { public PagedIterator _iterator(int pageSize) { diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index 7c3052a817..c9835677ea 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -45,6 +45,7 @@ import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.NoSuchElementException; import java.util.regex.Matcher; @@ -130,6 +131,14 @@ public Requester with(String key, Boolean value) { return _with(key, value); } + public Requester with(String key, Enum e) { + if (e==null) return _with(key, null); + + // by convention Java constant names are upper cases, but github uses + // lower-case constants. GitHub also uses '-', which in Java we always + // replace by '_' + return with(key, e.toString().toLowerCase(Locale.ENGLISH).replace('_','-')); + } public Requester with(String key, String value) { return _with(key, value); From d5809e375cdb033df869949b88d3af46ffd35710 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Thu, 10 Dec 2015 06:33:49 -0800 Subject: [PATCH 081/390] Simplification via enum handling in 'req.with' --- .../github/GHDeploymentStatusBuilder.java | 2 +- .../kohsuke/github/GHIssueSearchBuilder.java | 2 +- .../java/org/kohsuke/github/GHMyself.java | 5 ++-- .../org/kohsuke/github/GHOrganization.java | 2 +- .../java/org/kohsuke/github/GHRepository.java | 23 ++++++++----------- .../github/GHRepositorySearchBuilder.java | 2 +- .../kohsuke/github/GHUserSearchBuilder.java | 2 +- .../org/kohsuke/github/PagedIterable.java | 2 +- .../kohsuke/github/PagedSearchIterable.java | 2 +- 9 files changed, 18 insertions(+), 24 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java b/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java index b1ecf8918c..18cf5464ac 100644 --- a/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java +++ b/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java @@ -12,7 +12,7 @@ public GHDeploymentStatusBuilder(GHRepository repo, int deploymentId, GHDeployme this.repo = repo; this.deploymentId = deploymentId; this.builder = new Requester(repo.root); - this.builder.with("state",state.toString().toLowerCase(Locale.ENGLISH)); + this.builder.with("state",state); } public GHDeploymentStatusBuilder description(String description) { diff --git a/src/main/java/org/kohsuke/github/GHIssueSearchBuilder.java b/src/main/java/org/kohsuke/github/GHIssueSearchBuilder.java index c3054b1067..ff574025c0 100644 --- a/src/main/java/org/kohsuke/github/GHIssueSearchBuilder.java +++ b/src/main/java/org/kohsuke/github/GHIssueSearchBuilder.java @@ -42,7 +42,7 @@ public GHIssueSearchBuilder isMerged() { } public GHIssueSearchBuilder sort(Sort sort) { - req.with("sort",sort.toString().toLowerCase(Locale.ENGLISH)); + req.with("sort",sort); return this; } diff --git a/src/main/java/org/kohsuke/github/GHMyself.java b/src/main/java/org/kohsuke/github/GHMyself.java index c473af4806..c7ae80dd79 100644 --- a/src/main/java/org/kohsuke/github/GHMyself.java +++ b/src/main/java/org/kohsuke/github/GHMyself.java @@ -159,8 +159,7 @@ public PagedIterable listRepositories(final int pageSize) { public PagedIterable listRepositories(final int pageSize, final RepositoryListFilter repoType) { return new PagedIterable() { public PagedIterator _iterator(int pageSize) { - return new PagedIterator(root.retrieve().asIterator("/user/repos?per_page=" + pageSize + - "&type=" + repoType.name().toLowerCase(Locale.ENGLISH), GHRepository[].class, pageSize)) { + return new PagedIterator(root.retrieve().with("type",repoType).asIterator("/user/repos", GHRepository[].class, pageSize)) { @Override protected void wrapUp(GHRepository[] page) { for (GHRepository c : page) @@ -168,7 +167,7 @@ protected void wrapUp(GHRepository[] page) { } }; } - }; + }.withPageSize(pageSize); } /** diff --git a/src/main/java/org/kohsuke/github/GHOrganization.java b/src/main/java/org/kohsuke/github/GHOrganization.java index 2f4a6c0f4f..83c8a0474a 100644 --- a/src/main/java/org/kohsuke/github/GHOrganization.java +++ b/src/main/java/org/kohsuke/github/GHOrganization.java @@ -175,7 +175,7 @@ public enum Permission { ADMIN, PUSH, PULL } * Creates a new team and assigns the repositories. */ public GHTeam createTeam(String name, Permission p, Collection repositories) throws IOException { - Requester post = new Requester(root).with("name", name).with("permission", p.name().toLowerCase(Locale.ENGLISH)); + Requester post = new Requester(root).with("name", name).with("permission", p); List repo_names = new ArrayList(); for (GHRepository r : repositories) { repo_names.add(r.getName()); diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 38a821143a..b024814625 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -228,11 +228,10 @@ public List getIssues(GHIssueState state) throws IOException { public List 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(Locale.ENGLISH), - milestone == null ? "none" : "" + milestone.getNumber())), - GHIssue[].class - ), this)); + .with("state", state) + .with("milestone", milestone == null ? "none" : "" + milestone.getNumber()) + .to(getApiTailUrl("issues"), + GHIssue[].class), this)); } /** @@ -241,7 +240,7 @@ public List getIssues(GHIssueState state, GHMilestone milestone) throws public PagedIterable listIssues(final GHIssueState state) { return new PagedIterable() { public PagedIterator _iterator(int pageSize) { - return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("issues?state="+state.toString().toLowerCase(Locale.ENGLISH)), GHIssue[].class, pageSize)) { + return new PagedIterator(root.retrieve().with("state",state).asIterator(getApiTailUrl("issues"), GHIssue[].class, pageSize)) { @Override protected void wrapUp(GHIssue[] page) { for (GHIssue c : page) @@ -538,7 +537,7 @@ public void delete() throws IOException { /** * Sort orders for listing forks */ - public static enum ForkSort { NEWEST, OLDEST, STARGAZERS } + public enum ForkSort { NEWEST, OLDEST, STARGAZERS } /** * Lists all the direct forks of this repository, sorted by @@ -556,11 +555,7 @@ public PagedIterable listForks() { public PagedIterable listForks(final ForkSort sort) { return new PagedIterable() { public PagedIterator _iterator(int pageSize) { - String sortParam = ""; - if (sort != null) { - sortParam = "?sort=" + sort.toString().toLowerCase(Locale.ENGLISH); - } - return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("forks" + sortParam), GHRepository[].class, pageSize)) { + return new PagedIterator(root.retrieve().with("sort",sort).asIterator(getApiTailUrl("forks"), GHRepository[].class, pageSize)) { @Override protected void wrapUp(GHRepository[] page) { for (GHRepository c : page) { @@ -857,7 +852,7 @@ public GHCommitStatus getLastCommitStatus(String sha1) throws IOException { */ public GHCommitStatus createCommitStatus(String sha1, GHCommitState state, String targetUrl, String description, String context) throws IOException { return new Requester(root) - .with("state", state.name().toLowerCase(Locale.ENGLISH)) + .with("state", state) .with("target_url", targetUrl) .with("description", description) .with("context", context) @@ -1089,7 +1084,7 @@ public Map getMilestones() throws IOException { public PagedIterable listMilestones(final GHIssueState state) { return new PagedIterable() { public PagedIterator _iterator(int pageSize) { - return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("milestones?state="+state.toString().toLowerCase(Locale.ENGLISH)), GHMilestone[].class, pageSize)) { + return new PagedIterator(root.retrieve().with("state",state).asIterator(getApiTailUrl("milestones"), GHMilestone[].class, pageSize)) { @Override protected void wrapUp(GHMilestone[] page) { for (GHMilestone c : page) diff --git a/src/main/java/org/kohsuke/github/GHRepositorySearchBuilder.java b/src/main/java/org/kohsuke/github/GHRepositorySearchBuilder.java index cbcbb9e19d..8d30aaaf6b 100644 --- a/src/main/java/org/kohsuke/github/GHRepositorySearchBuilder.java +++ b/src/main/java/org/kohsuke/github/GHRepositorySearchBuilder.java @@ -58,7 +58,7 @@ public GHRepositorySearchBuilder stars(String v) { } public GHRepositorySearchBuilder sort(Sort sort) { - req.with("sort",sort.toString().toLowerCase(Locale.ENGLISH)); + req.with("sort",sort); return this; } diff --git a/src/main/java/org/kohsuke/github/GHUserSearchBuilder.java b/src/main/java/org/kohsuke/github/GHUserSearchBuilder.java index ee0c5f62a0..fa5161683f 100644 --- a/src/main/java/org/kohsuke/github/GHUserSearchBuilder.java +++ b/src/main/java/org/kohsuke/github/GHUserSearchBuilder.java @@ -50,7 +50,7 @@ public GHUserSearchBuilder followers(String v) { } public GHUserSearchBuilder sort(Sort sort) { - req.with("sort",sort.toString().toLowerCase(Locale.ENGLISH)); + req.with("sort",sort); return this; } diff --git a/src/main/java/org/kohsuke/github/PagedIterable.java b/src/main/java/org/kohsuke/github/PagedIterable.java index af6406a8cd..41c5bfdb0c 100644 --- a/src/main/java/org/kohsuke/github/PagedIterable.java +++ b/src/main/java/org/kohsuke/github/PagedIterable.java @@ -23,7 +23,7 @@ public abstract class PagedIterable implements Iterable { *

* When set to non-zero, each API call will retrieve this many entries. */ - public PagedIterable withPageSize(int size) throws IOException { + public PagedIterable withPageSize(int size) { this.size = size; return this; } diff --git a/src/main/java/org/kohsuke/github/PagedSearchIterable.java b/src/main/java/org/kohsuke/github/PagedSearchIterable.java index 6cd26c3a94..1efe49a1ef 100644 --- a/src/main/java/org/kohsuke/github/PagedSearchIterable.java +++ b/src/main/java/org/kohsuke/github/PagedSearchIterable.java @@ -25,7 +25,7 @@ public abstract class PagedSearchIterable extends PagedIterable { } @Override - public PagedSearchIterable withPageSize(int size) throws IOException { + public PagedSearchIterable withPageSize(int size) { return (PagedSearchIterable)super.withPageSize(size); } From 733d78abddbec74af5e78288c390928b0fff03f3 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Thu, 10 Dec 2015 06:59:37 -0800 Subject: [PATCH 082/390] [maven-release-plugin] prepare release github-api-1.72 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 0157b91a59..805080b06e 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.72-SNAPSHOT + 1.72 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - HEAD + github-api-1.72 From d91388aba4f6966938d15ad61076dd5afc8af4a3 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Thu, 10 Dec 2015 07:00:06 -0800 Subject: [PATCH 083/390] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 805080b06e..a81a8e0fe7 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.72 + 1.73-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - github-api-1.72 + HEAD From ac39b564a83f3788501c0e3caac5566eab914efd Mon Sep 17 00:00:00 2001 From: Daniel Lovera Date: Sun, 13 Dec 2015 20:59:49 +0100 Subject: [PATCH 084/390] Support for auto_init parameter The GitHub api auto_init parameter allows to initialize created repository with a readme file. Add a createRepository method using auto_init parameter. Already existing createRepository method uses auto_init parameter as false for retro-compatibility. --- src/main/java/org/kohsuke/github/GitHub.java | 18 ++++++++++++++++-- src/test/java/org/kohsuke/github/AppTest.java | 12 ++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index b6ddd6e965..55d1bcac5f 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -417,9 +417,23 @@ public T parseEventPayload(Reader r, Class type) t * Newly created repository. */ public GHRepository createRepository(String name, String description, String homepage, boolean isPublic) throws IOException { + return createRepository(name, description, homepage, isPublic, false); + } + + /** + * Creates a new repository. + * + * To create a repository in an organization, see + * {@link GHOrganization#createRepository(String, String, String, GHTeam, boolean, boolean)} + * + * @return + * Newly created repository. + */ + public GHRepository createRepository(String name, String description, String homepage, boolean isPublic, boolean autoInit) throws IOException { Requester requester = new Requester(this) - .with("name", name).with("description", description).with("homepage", homepage) - .with("public", isPublic ? 1 : 0); + .with("name", name).with("description", description).with("homepage", homepage) + .with("public", isPublic ? 1 : 0) + .with("auto_init", autoInit); return requester.method("POST").to("/user/repos", GHRepository.class).wrap(this); } diff --git a/src/test/java/org/kohsuke/github/AppTest.java b/src/test/java/org/kohsuke/github/AppTest.java index 5d5e0a5fef..0ccd0d11c3 100755 --- a/src/test/java/org/kohsuke/github/AppTest.java +++ b/src/test/java/org/kohsuke/github/AppTest.java @@ -38,6 +38,18 @@ public void testRepoCRUD() throws Exception { getUser().getRepository(targetName).delete(); } + @Test + public void testRepositoryWithAutoInitializationCRUD() throws IOException { + String name = "github-api-test-autoinit"; + deleteRepository(name); + GHRepository r = gitHub.createRepository(name, "a test repository for auto init", "http://github-api.kohsuke.org/", true, true); + r.enableIssueTracker(false); + r.enableDownloads(false); + r.enableWiki(false); + assertNotNull(r.getReadme()); + getUser().getRepository(name).delete(); + } + private void deleteRepository(final String name) throws IOException { GHRepository repository = getUser().getRepository(name); if(repository != null) { From c879e9e34d00c3d8f91ea04b028e028b86afff67 Mon Sep 17 00:00:00 2001 From: Daniel Lovera Date: Sun, 13 Dec 2015 21:00:40 +0100 Subject: [PATCH 085/390] Support for auto_init parameter in organization The GitHub api auto_init parameter allows to initialize created repository with a readme file. Add createRepository methods in GHOrganization using auto_init parameter. Already existing createRepository methods use auto_init parameter as false for retro-compatibility. --- .../org/kohsuke/github/GHOrganization.java | 16 ++++++--- .../kohsuke/github/GHOrganizationTest.java | 36 +++++++++++++++++++ 2 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 src/test/java/org/kohsuke/github/GHOrganizationTest.java diff --git a/src/main/java/org/kohsuke/github/GHOrganization.java b/src/main/java/org/kohsuke/github/GHOrganization.java index 83c8a0474a..9c4a42042f 100644 --- a/src/main/java/org/kohsuke/github/GHOrganization.java +++ b/src/main/java/org/kohsuke/github/GHOrganization.java @@ -26,19 +26,27 @@ public class GHOrganization extends GHPerson { * Newly created repository. */ public GHRepository createRepository(String name, String description, String homepage, String team, boolean isPublic) throws IOException { + return createRepository(name, description, homepage, team, isPublic, false); + } + + public GHRepository createRepository(String name, String description, String homepage, String team, boolean isPublic, boolean autoInit) throws IOException { 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, autoInit); } public GHRepository createRepository(String name, String description, String homepage, GHTeam team, boolean isPublic) throws IOException { + return createRepository(name, description, homepage, team, isPublic, false); + } + + public GHRepository createRepository(String name, String description, String homepage, GHTeam team, boolean isPublic, boolean autoInit) throws IOException { if (team==null) throw new IllegalArgumentException("Invalid team"); // such API doesn't exist, so fall back to HTML scraping return new Requester(root) - .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); + .with("name", name).with("description", description).with("homepage", homepage) + .with("public", isPublic).with("auto_init", autoInit).with("team_id",team.getId()).to("/orgs/"+login+"/repos", GHRepository.class).wrap(root); } /** @@ -185,7 +193,7 @@ public GHTeam createTeam(String name, Permission p, Collection rep } public GHTeam createTeam(String name, Permission p, GHRepository... repositories) throws IOException { - return createTeam(name,p, Arrays.asList(repositories)); + return createTeam(name, p, Arrays.asList(repositories)); } /** diff --git a/src/test/java/org/kohsuke/github/GHOrganizationTest.java b/src/test/java/org/kohsuke/github/GHOrganizationTest.java new file mode 100644 index 0000000000..3f425f3fef --- /dev/null +++ b/src/test/java/org/kohsuke/github/GHOrganizationTest.java @@ -0,0 +1,36 @@ +package org.kohsuke.github; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Test; + +import java.io.IOException; + +public class GHOrganizationTest extends AbstractGitHubApiTestBase { + + public static final String GITHUB_API_TEST_ORG = "github-api-test-org"; + public static final String GITHUB_API_TEST = "github-api-test"; + + @Test + public void testCreateRepository() throws IOException { + GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); + GHRepository repository = org.createRepository(GITHUB_API_TEST, + "a test repository used to test kohsuke's github-api", "http://github-api.kohsuke.org/", "Core Developers", true); + Assert.assertNotNull(repository); + } + + @Test + public void testCreateRepositoryWithAutoInitialization() throws IOException { + GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); + GHRepository repository = org.createRepository(GITHUB_API_TEST, + "a test repository used to test kohsuke's github-api", "http://github-api.kohsuke.org/", "Core Developers", true, true); + Assert.assertNotNull(repository); + Assert.assertNotNull(repository.getReadme()); + } + + @After + public void cleanUp() throws Exception { + GHRepository repository = gitHub.getOrganization(GITHUB_API_TEST_ORG).getRepository(GITHUB_API_TEST); + repository.delete(); + } +} From e94c36b7e6f4cb18d3403a05994a03b528584e2e Mon Sep 17 00:00:00 2001 From: Daniel Lovera Date: Sun, 13 Dec 2015 21:05:36 +0100 Subject: [PATCH 086/390] clean: remove unused import --- src/main/java/org/kohsuke/github/GHOrganization.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHOrganization.java b/src/main/java/org/kohsuke/github/GHOrganization.java index 9c4a42042f..33daecd591 100644 --- a/src/main/java/org/kohsuke/github/GHOrganization.java +++ b/src/main/java/org/kohsuke/github/GHOrganization.java @@ -7,7 +7,6 @@ import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.TreeMap; From f573f83fb9232a8a8bbbdf185824529e9741c063 Mon Sep 17 00:00:00 2001 From: benbek Date: Tue, 19 Jan 2016 00:05:01 +0200 Subject: [PATCH 087/390] Amendment to the documentation The status reported by GitHub for deleting a file is actually "removed", not "deleted". --- src/main/java/org/kohsuke/github/GHCommit.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHCommit.java b/src/main/java/org/kohsuke/github/GHCommit.java index a350eeb535..031e15c315 100644 --- a/src/main/java/org/kohsuke/github/GHCommit.java +++ b/src/main/java/org/kohsuke/github/GHCommit.java @@ -102,7 +102,7 @@ public int getLinesDeleted() { } /** - * "modified", "added", or "deleted" + * "modified", "added", or "removed" */ public String getStatus() { return status; From 33d95d3e3a2ace95682a34f60f1e25e831541089 Mon Sep 17 00:00:00 2001 From: Daniel Beck Date: Wed, 20 Jan 2016 23:30:10 +0100 Subject: [PATCH 088/390] Fix error when creating email service hook --- src/main/java/org/kohsuke/github/GHRepository.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index b024814625..fbd64709a6 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -475,7 +475,7 @@ private void modifyCollaborators(Collection users, String method) throws public void setEmailServiceHook(String address) throws IOException { Map config = new HashMap(); config.put("address", address); - new Requester(root).method("POST").with("name", "email").with("config", config).with("active", "true") + new Requester(root).method("POST").with("name", "email").with("config", config).with("active", true) .to(getApiTailUrl("hooks")); } From c0a05e06501bc162ec15afeaf364964646323cf5 Mon Sep 17 00:00:00 2001 From: Daniel Beck Date: Sun, 21 Feb 2016 01:26:43 +0100 Subject: [PATCH 089/390] Populate commit with data for getCommitShortInfo --- src/main/java/org/kohsuke/github/GHCommit.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHCommit.java b/src/main/java/org/kohsuke/github/GHCommit.java index a350eeb535..ee6131709e 100644 --- a/src/main/java/org/kohsuke/github/GHCommit.java +++ b/src/main/java/org/kohsuke/github/GHCommit.java @@ -178,7 +178,8 @@ static class User { User author,committer; - public ShortInfo getCommitShortInfo() { + public ShortInfo getCommitShortInfo() throws IOException { + populate(); return commit; } From f4b129b9f10928f05bd9cdb589fbcfe2d642206c Mon Sep 17 00:00:00 2001 From: Artem Gubanov Date: Thu, 25 Feb 2016 10:46:17 +0200 Subject: [PATCH 090/390] Added getHtmlUrl() to GHCommit --- src/main/java/org/kohsuke/github/GHCommit.java | 9 ++++++++- src/test/java/org/kohsuke/github/AppTest.java | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHCommit.java b/src/main/java/org/kohsuke/github/GHCommit.java index a350eeb535..c7825b88bc 100644 --- a/src/main/java/org/kohsuke/github/GHCommit.java +++ b/src/main/java/org/kohsuke/github/GHCommit.java @@ -171,7 +171,7 @@ static class User { String login; } - String url,sha; + String url,html_url,sha; List files; Stats stats; List parents; @@ -213,6 +213,13 @@ public int getLinesDeleted() throws IOException { return stats.deletions; } + /** + * URL of this commit like "https://github.com/kohsuke/sandbox-ant/commit/8ae38db0ea5837313ab5f39d43a6f73de3bd9000" + */ + public URL getHtmlUrl() { + return GitHub.parseURL(html_url); + } + /** * [0-9a-f]{40} SHA1 checksum. */ diff --git a/src/test/java/org/kohsuke/github/AppTest.java b/src/test/java/org/kohsuke/github/AppTest.java index 5d5e0a5fef..82952a7960 100755 --- a/src/test/java/org/kohsuke/github/AppTest.java +++ b/src/test/java/org/kohsuke/github/AppTest.java @@ -326,6 +326,8 @@ public void testCommit() throws Exception { System.out.println(commit); assertEquals(1, commit.getParents().size()); assertEquals(1,commit.getFiles().size()); + assertEquals("https://github.com/jenkinsci/jenkins/commit/08c1c9970af4d609ae754fbe803e06186e3206f7", + commit.getHtmlUrl().toString()); File f = commit.getFiles().get(0); assertEquals(48,f.getLinesChanged()); From d80ad778710f17f60ecf86c11de4d3d46a551ff1 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Mon, 29 Feb 2016 19:57:16 -0800 Subject: [PATCH 091/390] Use builder pattern to support all the other options --- .../github/GHCreateRepositoryBuilder.java | 114 ++++++++++++++++++ .../org/kohsuke/github/GHOrganization.java | 32 +++-- src/main/java/org/kohsuke/github/GitHub.java | 27 ++--- src/test/java/org/kohsuke/github/AppTest.java | 5 +- .../kohsuke/github/GHOrganizationTest.java | 19 ++- 5 files changed, 162 insertions(+), 35 deletions(-) create mode 100644 src/main/java/org/kohsuke/github/GHCreateRepositoryBuilder.java diff --git a/src/main/java/org/kohsuke/github/GHCreateRepositoryBuilder.java b/src/main/java/org/kohsuke/github/GHCreateRepositoryBuilder.java new file mode 100644 index 0000000000..492aaf5c81 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHCreateRepositoryBuilder.java @@ -0,0 +1,114 @@ +package org.kohsuke.github; + +import java.io.IOException; +import java.net.URL; + +/** + * Creates a repository + * + * @author Kohsuke Kawaguchi + */ +public class GHCreateRepositoryBuilder { + private final GitHub root; + protected final Requester builder; + private final String apiUrlTail; + + /*package*/ GHCreateRepositoryBuilder(GitHub root, String apiUrlTail, String name) { + this.root = root; + this.apiUrlTail = apiUrlTail; + this.builder = new Requester(root); + this.builder.with("name",name); + } + + public GHCreateRepositoryBuilder description(String description) { + this.builder.with("description",description); + return this; + } + + public GHCreateRepositoryBuilder homepage(URL homepage) { + return homepage(homepage.toExternalForm()); + } + + public GHCreateRepositoryBuilder homepage(String homepage) { + this.builder.with("homepage",homepage); + return this; + } + + /** + * Creates a private repository + */ + public GHCreateRepositoryBuilder private_(boolean b) { + this.builder.with("private",b); + return this; + } + + /** + * Enables issue tracker + */ + public GHCreateRepositoryBuilder issues(boolean b) { + this.builder.with("has_issues",b); + return this; + } + + /** + * Enables wiki + */ + public GHCreateRepositoryBuilder wiki(boolean b) { + this.builder.with("has_wiki",b); + return this; + } + + /** + * Enables downloads + */ + public GHCreateRepositoryBuilder downloads(boolean b) { + this.builder.with("has_downloads",b); + return this; + } + + /** + * If true, create an initial commit with empty README. + */ + public GHCreateRepositoryBuilder autoInit(boolean b) { + this.builder.with("auto_init",b); + return this; + } + + /** + * Creates a default .gitignore + * + * See https://developer.github.com/v3/repos/#create + */ + public GHCreateRepositoryBuilder gitignoreTemplate(String language) { + this.builder.with("gitignore_template",language); + return this; + } + + /** + * Desired license template to apply + * + * See https://developer.github.com/v3/repos/#create + */ + public GHCreateRepositoryBuilder licenseTemplate(String license) { + this.builder.with("license_template",license); + return this; + } + + /** + * The team that gets granted access to this repository. Only valid for creating a repository in + * an organization. + */ + public GHCreateRepositoryBuilder team(GHTeam team) { + if (team!=null) + this.builder.with("team_id",team.getId()); + return this; + } + + /** + * Creates a repository with all the parameters. + */ + public GHRepository create() throws IOException { + return builder.method("POST").to(apiUrlTail, GHRepository.class).wrap(root); + } + +} diff --git a/src/main/java/org/kohsuke/github/GHOrganization.java b/src/main/java/org/kohsuke/github/GHOrganization.java index 33daecd591..c4ae92e6db 100644 --- a/src/main/java/org/kohsuke/github/GHOrganization.java +++ b/src/main/java/org/kohsuke/github/GHOrganization.java @@ -23,29 +23,35 @@ public class GHOrganization extends GHPerson { * * @return * Newly created repository. + * @deprecated + * Use {@link #createRepository(String)} that uses a builder pattern to let you control every aspect. */ public GHRepository createRepository(String name, String description, String homepage, String team, boolean isPublic) throws IOException { - return createRepository(name, description, homepage, team, isPublic, false); - } - - public GHRepository createRepository(String name, String description, String homepage, String team, boolean isPublic, boolean autoInit) throws IOException { GHTeam t = getTeams().get(team); if (t==null) throw new IllegalArgumentException("No such team: "+team); - return createRepository(name, description, homepage, t, isPublic, autoInit); + return createRepository(name, description, homepage, t, isPublic); } + /** + * @deprecated + * Use {@link #createRepository(String)} that uses a builder pattern to let you control every aspect. + */ public GHRepository createRepository(String name, String description, String homepage, GHTeam team, boolean isPublic) throws IOException { - return createRepository(name, description, homepage, team, isPublic, false); - } - - public GHRepository createRepository(String name, String description, String homepage, GHTeam team, boolean isPublic, boolean autoInit) throws IOException { if (team==null) throw new IllegalArgumentException("Invalid team"); - // such API doesn't exist, so fall back to HTML scraping - return new Requester(root) - .with("name", name).with("description", description).with("homepage", homepage) - .with("public", isPublic).with("auto_init", autoInit).with("team_id",team.getId()).to("/orgs/"+login+"/repos", GHRepository.class).wrap(root); + return createRepository(name).description(description).homepage(homepage).private_(!isPublic).team(team).create(); + } + + /** + * Starts a builder that creates a new repository. + * + *

+ * You use the returned builder to set various properties, then call {@link GHCreateRepositoryBuilder#create()} + * to finally createa repository. + */ + public GHCreateRepositoryBuilder createRepository(String name) throws IOException { + return new GHCreateRepositoryBuilder(root,"/orgs/"+login+"/repos",name); } /** diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 55d1bcac5f..77d178800c 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -410,31 +410,28 @@ public T parseEventPayload(Reader r, Class type) t /** * Creates a new repository. * - * To create a repository in an organization, see - * {@link GHOrganization#createRepository(String, String, String, GHTeam, boolean)} - * * @return * Newly created repository. + * @deprecated + * Use {@link #createRepository(String)} that uses a builder pattern to let you control every aspect. */ public GHRepository createRepository(String name, String description, String homepage, boolean isPublic) throws IOException { - return createRepository(name, description, homepage, isPublic, false); + return createRepository(name).description(description).homepage(homepage).private_(!isPublic).create(); } /** - * Creates a new repository. + * Starts a builder that creates a new repository. * - * To create a repository in an organization, see - * {@link GHOrganization#createRepository(String, String, String, GHTeam, boolean, boolean)} + *

+ * You use the returned builder to set various properties, then call {@link GHCreateRepositoryBuilder#create()} + * to finally createa repository. * - * @return - * Newly created repository. + *

+ * To create a repository in an organization, see + * {@link GHOrganization#createRepository(String, String, String, GHTeam, boolean)} */ - public GHRepository createRepository(String name, String description, String homepage, boolean isPublic, boolean autoInit) throws IOException { - Requester requester = new Requester(this) - .with("name", name).with("description", description).with("homepage", homepage) - .with("public", isPublic ? 1 : 0) - .with("auto_init", autoInit); - return requester.method("POST").to("/user/repos", GHRepository.class).wrap(this); + public GHCreateRepositoryBuilder createRepository(String name) { + return new GHCreateRepositoryBuilder(this,"/user/repos",name); } /** diff --git a/src/test/java/org/kohsuke/github/AppTest.java b/src/test/java/org/kohsuke/github/AppTest.java index 0ccd0d11c3..c3a7d6a437 100755 --- a/src/test/java/org/kohsuke/github/AppTest.java +++ b/src/test/java/org/kohsuke/github/AppTest.java @@ -42,7 +42,10 @@ public void testRepoCRUD() throws Exception { public void testRepositoryWithAutoInitializationCRUD() throws IOException { String name = "github-api-test-autoinit"; deleteRepository(name); - GHRepository r = gitHub.createRepository(name, "a test repository for auto init", "http://github-api.kohsuke.org/", true, true); + GHRepository r = gitHub.createRepository(name) + .description("a test repository for auto init") + .homepage("http://github-api.kohsuke.org/") + .autoInit(true).create(); r.enableIssueTracker(false); r.enableDownloads(false); r.enableWiki(false); diff --git a/src/test/java/org/kohsuke/github/GHOrganizationTest.java b/src/test/java/org/kohsuke/github/GHOrganizationTest.java index 3f425f3fef..a1c5d3b921 100644 --- a/src/test/java/org/kohsuke/github/GHOrganizationTest.java +++ b/src/test/java/org/kohsuke/github/GHOrganizationTest.java @@ -8,12 +8,17 @@ public class GHOrganizationTest extends AbstractGitHubApiTestBase { - public static final String GITHUB_API_TEST_ORG = "github-api-test-org"; public static final String GITHUB_API_TEST = "github-api-test"; + private GHOrganization org; + + @Override + public void setUp() throws Exception { + super.setUp(); + org = gitHub.getOrganization("github-api-test-org"); + } @Test public void testCreateRepository() throws IOException { - GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); GHRepository repository = org.createRepository(GITHUB_API_TEST, "a test repository used to test kohsuke's github-api", "http://github-api.kohsuke.org/", "Core Developers", true); Assert.assertNotNull(repository); @@ -21,16 +26,18 @@ public void testCreateRepository() throws IOException { @Test public void testCreateRepositoryWithAutoInitialization() throws IOException { - GHOrganization org = gitHub.getOrganization(GITHUB_API_TEST_ORG); - GHRepository repository = org.createRepository(GITHUB_API_TEST, - "a test repository used to test kohsuke's github-api", "http://github-api.kohsuke.org/", "Core Developers", true, true); + GHRepository repository = org.createRepository(GITHUB_API_TEST) + .description("a test repository used to test kohsuke's github-api") + .homepage("http://github-api.kohsuke.org/") + .team(org.getTeamByName("Core Developers")) + .autoInit(true).create(); Assert.assertNotNull(repository); Assert.assertNotNull(repository.getReadme()); } @After public void cleanUp() throws Exception { - GHRepository repository = gitHub.getOrganization(GITHUB_API_TEST_ORG).getRepository(GITHUB_API_TEST); + GHRepository repository = org.getRepository(GITHUB_API_TEST); repository.delete(); } } From 14f7198a07fc5365eafbd708388bf0e6f6a8d971 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Mon, 29 Feb 2016 20:56:28 -0800 Subject: [PATCH 092/390] Handle "all" webhook correctly This fixes #250 --- src/main/java/org/kohsuke/github/GHEvent.java | 17 ++++++++++++++++- src/main/java/org/kohsuke/github/GHHook.java | 6 ++++-- src/main/java/org/kohsuke/github/GHHooks.java | 2 +- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHEvent.java b/src/main/java/org/kohsuke/github/GHEvent.java index 9e172146ae..e8e79bb456 100644 --- a/src/main/java/org/kohsuke/github/GHEvent.java +++ b/src/main/java/org/kohsuke/github/GHEvent.java @@ -1,5 +1,7 @@ package org.kohsuke.github; +import java.util.Locale; + /** * Hook event type. * @@ -33,5 +35,18 @@ public enum GHEvent { STATUS, TEAM_ADD, WATCH, - PING + PING, + /** + * Special event type that means "every possible event" + */ + ALL; + + + /** + * Returns GitHub's internal representation of this event. + */ + String symbol() { + if (this==ALL) return "*"; + return name().toLowerCase(Locale.ENGLISH); + } } diff --git a/src/main/java/org/kohsuke/github/GHHook.java b/src/main/java/org/kohsuke/github/GHHook.java index 7d63f9d950..73b2eb4364 100644 --- a/src/main/java/org/kohsuke/github/GHHook.java +++ b/src/main/java/org/kohsuke/github/GHHook.java @@ -26,8 +26,10 @@ public String getName() { public EnumSet getEvents() { EnumSet s = EnumSet.noneOf(GHEvent.class); - for (String e : events) - s.add(Enum.valueOf(GHEvent.class,e.toUpperCase(Locale.ENGLISH))); + for (String e : events) { + if (e.equals("*")) s.add(GHEvent.ALL); + else s.add(Enum.valueOf(GHEvent.class, e.toUpperCase(Locale.ENGLISH))); + } return s; } diff --git a/src/main/java/org/kohsuke/github/GHHooks.java b/src/main/java/org/kohsuke/github/GHHooks.java index 4ee939c5a8..6f64587b17 100644 --- a/src/main/java/org/kohsuke/github/GHHooks.java +++ b/src/main/java/org/kohsuke/github/GHHooks.java @@ -39,7 +39,7 @@ public GHHook createHook(String name, Map config, Collection(); for (GHEvent e : events) - ea.add(e.name().toLowerCase(Locale.ENGLISH)); + ea.add(e.symbol()); } GHHook hook = new Requester(root) From 751043bf81a5e3afe3ac15300ca198c5d6a220a4 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Mon, 29 Feb 2016 21:01:18 -0800 Subject: [PATCH 093/390] change in the markup generated --- src/test/java/org/kohsuke/github/AppTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/kohsuke/github/AppTest.java b/src/test/java/org/kohsuke/github/AppTest.java index f9fb4c95b3..c8d523cd81 100755 --- a/src/test/java/org/kohsuke/github/AppTest.java +++ b/src/test/java/org/kohsuke/github/AppTest.java @@ -791,7 +791,7 @@ public void markDown() throws Exception { assertTrue(actual.contains("href=\"https://github.com/kohsuke\"")); assertTrue(actual.contains("href=\"https://github.com/kohsuke/github-api/pull/1\"")); assertTrue(actual.contains("class=\"user-mention\"")); - assertTrue(actual.contains("class=\"issue-link\"")); + assertTrue(actual.contains("class=\"issue-link ")); assertTrue(actual.contains("to fix issue")); } From 013eaa30b64a33c70231844e1c52fdbfcd630d27 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Mon, 29 Feb 2016 21:03:31 -0800 Subject: [PATCH 094/390] [maven-release-plugin] prepare release github-api-1.73 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index a81a8e0fe7..05d286b718 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.73-SNAPSHOT + 1.73 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - HEAD + github-api-1.73 From 54c3070607fb1957c89aa224cdf99f3445311379 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Mon, 29 Feb 2016 21:03:34 -0800 Subject: [PATCH 095/390] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 05d286b718..0af43488f1 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.73 + 1.74-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - github-api-1.73 + HEAD From dbc79f8c423749311495cb548c1a9cda1d8638cf Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Tue, 1 Mar 2016 19:46:50 -0800 Subject: [PATCH 096/390] Fixing issue raised in https://github.com/kohsuke/github-api/pull/247 From Shredder121, -------------------- Only the HttpURLConnection.method was set by that change. Not the Requester.method. This means that Requester.method is still set to POST, isMethodWithBody will return true, and uc.setDoOutput(true) will be called. I use Okhttp, and their HttpURLConnectionImpl's method changes to POST if you tell it to open a stream to write to. --- src/main/java/org/kohsuke/github/Requester.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index c9835677ea..af4819c3a1 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -264,10 +264,9 @@ private T _to(String tailApiUrl, Class type, T instance) throws IOExcepti */ public int asHttpStatusCode(String tailApiUrl) throws IOException { while (true) {// loop while API rate limit is hit + method("GET"); setupConnection(root.getApiURL(tailApiUrl)); - uc.setRequestMethod("GET"); - buildRequest(); try { @@ -280,12 +279,10 @@ public int asHttpStatusCode(String tailApiUrl) throws IOException { public InputStream asStream(String tailApiUrl) throws IOException { while (true) {// loop while API rate limit is hit + method("GET"); // if the download link is encoded with a token on the query string, the default behavior of POST will fail setupConnection(root.getApiURL(tailApiUrl)); - // if the download link is encoded with a token on the query string, the default behavior of POST will fail - uc.setRequestMethod("GET"); - - buildRequest(); + buildRequest(); try { return wrapStream(uc.getInputStream()); From ae85cf4b6c02ba9c330d436bbee39d211428755d Mon Sep 17 00:00:00 2001 From: Manuel Recena Date: Sat, 5 Mar 2016 17:42:25 +0100 Subject: [PATCH 097/390] Improve checkApiUrlValidity() method to support the private mode in GitHub Enterprise servers --- src/main/java/org/kohsuke/github/GitHub.java | 30 ++++++++++++++++++- .../java/org/kohsuke/github/GitHubTest.java | 7 ++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 77d178800c..14e7b13368 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -31,6 +31,7 @@ import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; +import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.text.ParseException; @@ -482,7 +483,34 @@ void check(String apiUrl) throws IOException { * Otherwise this method throws {@link IOException} to indicate the problem. */ public void checkApiUrlValidity() throws IOException { - retrieve().to("/", GHApiInfo.class).check(apiUrl); + try { + retrieve().to("/", GHApiInfo.class).check(apiUrl); + } catch (IOException ioe) { + if (isPrivateModeEnabled()) { + throw new IOException("GitHub Enterprise server (" + apiUrl + ") with private mode enabled"); + } + throw ioe; + } + } + + /** + * Ensures if a GitHub Enterprise server is configured in private mode. + * + * @return {@code true} if private mode is enabled. If it tries to use this method with GitHub, returns {@code + * false}. + */ + private boolean isPrivateModeEnabled() { + try { + HttpURLConnection connect = getConnector().connect(getApiURL("/")); + if (connect.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED + && connect.getHeaderField("Server") != null + && connect.getHeaderField("Server").equals("GitHub.com")) { + return true; + } + return false; + } catch (IOException e) { + return false; + } } /** diff --git a/src/test/java/org/kohsuke/github/GitHubTest.java b/src/test/java/org/kohsuke/github/GitHubTest.java index 1663d24144..b8ae4ff0df 100644 --- a/src/test/java/org/kohsuke/github/GitHubTest.java +++ b/src/test/java/org/kohsuke/github/GitHubTest.java @@ -124,6 +124,11 @@ public void testGitHubEnterpriseDoesNotHaveRateLimit() throws IOException { @Test public void testGitHubIsApiUrlValid() throws IOException { GitHub github = GitHub.connectAnonymously(); - github.checkApiUrlValidity(); + //GitHub github = GitHub.connectToEnterpriseAnonymously("https://github.mycompany.com/api/v3/"); + try { + github.checkApiUrlValidity(); + } catch (IOException ioe) { + assertTrue(ioe.getMessage().contains("private mode enabled")); + } } } From ba951cb6e301a56c673f00395e08e87d80422da3 Mon Sep 17 00:00:00 2001 From: Cyrille Le Clerc Date: Sun, 6 Mar 2016 18:09:36 +0100 Subject: [PATCH 098/390] Fix #252: infinite loop because the "hypertext engine" may duplicate '?' generating invalid "https://api.github.com/notifications?all=true&page=2?all=true" instead of "https://api.github.com/notifications?all=true&page=2&all=true". A better fix will be to prevent duplication of parameters ("all=true" in this case). --- .../java/org/kohsuke/github/Requester.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index af4819c3a1..5096f5ff49 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -45,6 +45,7 @@ import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; +import java.util.ListIterator; import java.util.Locale; import java.util.Map; import java.util.NoSuchElementException; @@ -219,15 +220,19 @@ public T to(String tailApiUrl, Class type, String method) throws IOExcept } private T _to(String tailApiUrl, Class type, T instance) throws IOException { - while (true) {// loop while API rate limit is hit - if (METHODS_WITHOUT_BODY.contains(method) && !args.isEmpty()) { - StringBuilder qs=new StringBuilder(); - for (Entry arg : args) { - qs.append(qs.length()==0 ? '?' : '&'); - qs.append(arg.key).append('=').append(URLEncoder.encode(arg.value.toString(),"UTF-8")); + if (METHODS_WITHOUT_BODY.contains(method) && !args.isEmpty()) { + boolean questionMarkFound = tailApiUrl.indexOf('?') != -1; + tailApiUrl += questionMarkFound ? '&' : '?'; + for (Iterator it = args.listIterator(); it.hasNext();) { + Entry arg = it.next(); + tailApiUrl += arg.key + '=' + URLEncoder.encode(arg.value.toString(),"UTF-8"); + if (it.hasNext()) { + tailApiUrl += '&'; } - tailApiUrl += qs.toString(); } + } + + while (true) {// loop while API rate limit is hit setupConnection(root.getApiURL(tailApiUrl)); buildRequest(); From 027e4b4f25390627b1ccc386e688246d07a2016d Mon Sep 17 00:00:00 2001 From: Cyrille Le Clerc Date: Sun, 6 Mar 2016 16:11:56 +0100 Subject: [PATCH 099/390] Better error message: introduce HttpException, subclass of IOException with url, http responseCode and http responseMessage to help exception handling. --- pom.xml | 8 ++ src/main/java/org/kohsuke/github/GitHub.java | 6 + .../org/kohsuke/github/HttpException.java | 119 ++++++++++++++++++ .../java/org/kohsuke/github/Requester.java | 28 ++++- 4 files changed, 157 insertions(+), 4 deletions(-) create mode 100644 src/main/java/org/kohsuke/github/HttpException.java diff --git a/pom.xml b/pom.xml index 0af43488f1..dde789075d 100644 --- a/pom.xml +++ b/pom.xml @@ -46,6 +46,14 @@ + + org.apache.maven.plugins + maven-compiler-plugin + + 1.6 + 1.6 + + org.codehaus.mojo findbugs-maven-plugin diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 77d178800c..fe94840fda 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -31,6 +31,7 @@ import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; +import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.text.ParseException; @@ -55,6 +56,8 @@ import com.fasterxml.jackson.databind.introspect.VisibilityChecker.Std; import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import java.nio.charset.Charset; +import java.util.logging.Level; +import java.util.logging.Logger; /** * Root of the GitHub API. @@ -68,6 +71,8 @@ * @author Kohsuke Kawaguchi */ public class GitHub { + protected final transient Logger logger = Logger.getLogger(getClass().getName()); + /*package*/ final String login; /** @@ -458,6 +463,7 @@ public boolean isCredentialValid() throws IOException { retrieve().to("/user", GHUser.class); return true; } catch (IOException e) { + logger.log(Level.FINEST, "Exception validating credentials on {0} with login {1}: {2}", new Object[]{this.apiUrl, this.login, e, e}); return false; } } diff --git a/src/main/java/org/kohsuke/github/HttpException.java b/src/main/java/org/kohsuke/github/HttpException.java new file mode 100644 index 0000000000..37c16f4a12 --- /dev/null +++ b/src/main/java/org/kohsuke/github/HttpException.java @@ -0,0 +1,119 @@ +package org.kohsuke.github; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; + +/** + * Http exception + * + * @author Cyrille Le Clerc + */ +public class HttpException extends IOException { + static final long serialVersionUID = 1L; + + private final int responseCode; + private final String responseMessage; + private final String url; + + /** + * @param message The detail message (which is saved for later retrieval + * by the {@link #getMessage()} method) + * @param responseCode Http response code. {@code -1} if no code can be discerned. + * @param responseMessage Http response message + * @param url The url that was invoked + * @see HttpURLConnection#getResponseCode() + * @see HttpURLConnection#getResponseMessage() + */ + public HttpException(String message, int responseCode, String responseMessage, String url) { + super(message); + this.responseCode = responseCode; + this.responseMessage = responseMessage; + this.url = url; + } + + /** + * @param message The detail message (which is saved for later retrieval + * by the {@link #getMessage()} method) + * @param responseCode Http response code. {@code -1} if no code can be discerned. + * @param responseMessage Http response message + * @param url The url that was invoked + * @param cause The cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A null value is permitted, + * and indicates that the cause is nonexistent or unknown.) + * @see HttpURLConnection#getResponseCode() + * @see HttpURLConnection#getResponseMessage() + */ + public HttpException(String message, int responseCode, String responseMessage, String url, Throwable cause) { + super(message, cause); + this.responseCode = responseCode; + this.responseMessage = responseMessage; + this.url = url; + } + + /** + * @param message The detail message (which is saved for later retrieval + * by the {@link #getMessage()} method) + * @param responseCode Http response code. {@code -1} if no code can be discerned. + * @param responseMessage Http response message + * @param url The url that was invoked + * @param cause The cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A null value is permitted, + * and indicates that the cause is nonexistent or unknown.) + * @see HttpURLConnection#getResponseCode() + * @see HttpURLConnection#getResponseMessage() + */ + public HttpException(int responseCode, String responseMessage, String url, Throwable cause) { + super("Server returned HTTP response code: " + responseCode + ", message: '" + responseMessage + "'" + + " for URL: " + url, cause); + this.responseCode = responseCode; + this.responseMessage = responseMessage; + this.url = url; + } + + /** + * @param responseCode Http response code. {@code -1} if no code can be discerned. + * @param responseMessage Http response message + * @param url The url that was invoked + * @param cause The cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A null value is permitted, + * and indicates that the cause is nonexistent or unknown.) + * @see HttpURLConnection#getResponseCode() + * @see HttpURLConnection#getResponseMessage() + */ + public HttpException(int responseCode, String responseMessage, URL url, Throwable cause) { + this(responseCode, responseMessage, url == null ? null : url.toString(), cause); + } + + /** + * Http response code of the request that cause the exception + * + * @return {@code -1} if no code can be discerned. + */ + public int getResponseCode() { + return responseCode; + } + + /** + * Http response message of the request that cause the exception + * + * @return {@code null} if no response message can be discerned. + */ + public String getResponseMessage() { + return responseMessage; + } + + /** + * The http URL that caused the exception + * + * @return url + */ + public String getUrl() { + return url; + } + + @Override + public String getMessage() { + return super.getMessage(); + } +} diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index af4819c3a1..4670b00a8e 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -473,21 +473,33 @@ private void setupConnection(URL url) throws IOException { } private T parse(Class type, T instance) throws IOException { - if (uc.getResponseCode()==304) - return null; // special case handling for 304 unmodified, as the content will be "" InputStreamReader r = null; + int responseCode = -1; + String responseMessage = null; try { + responseCode = uc.getResponseCode(); + responseMessage = uc.getResponseMessage(); + if (responseCode == 304) { + return null; // special case handling for 304 unmodified, as the content will be "" + } + r = new InputStreamReader(wrapStream(uc.getInputStream()), "UTF-8"); String data = IOUtils.toString(r); if (type!=null) try { return MAPPER.readValue(data,type); } catch (JsonMappingException e) { - throw (IOException)new IOException("Failed to deserialize "+data).initCause(e); + throw (IOException)new IOException("Failed to deserialize " +data).initCause(e); } if (instance!=null) return MAPPER.readerForUpdating(instance).readValue(data); return null; + } catch (FileNotFoundException e) { + // java.net.URLConnection handles 404 exception has FileNotFoundException, don't wrap exception in HttpException + // to preserve backward compatibility + throw e; + } catch (IOException e) { + throw new HttpException(responseCode, responseMessage, uc.getURL(), e); } finally { IOUtils.closeQuietly(r); } @@ -508,7 +520,15 @@ private InputStream wrapStream(InputStream in) throws IOException { * 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 + int responseCode; + try { + responseCode = uc.getResponseCode(); + } catch (IOException e2) { + // likely to be a network exception (e.g. SSLHandshakeException), + // uc.getResponseCode() and any other getter on the response will cause an exception + throw e; + } + if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) // 401 / Unauthorized == bad creds throw e; if ("0".equals(uc.getHeaderField("X-RateLimit-Remaining"))) { From 56379bb3b99ea8c25cf85c0a3577fa633d2c5eec Mon Sep 17 00:00:00 2001 From: Cyrille Le Clerc Date: Mon, 7 Mar 2016 19:25:42 +0100 Subject: [PATCH 100/390] Fix broken log message in GitHub.java and cleanup code as recommended by @jglick --- src/main/java/org/kohsuke/github/GitHub.java | 3 ++- src/main/java/org/kohsuke/github/HttpException.java | 13 ++++++------- src/main/java/org/kohsuke/github/Requester.java | 9 ++++++++- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index fe94840fda..850edaf531 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -463,7 +463,8 @@ public boolean isCredentialValid() throws IOException { retrieve().to("/user", GHUser.class); return true; } catch (IOException e) { - logger.log(Level.FINEST, "Exception validating credentials on {0} with login {1}: {2}", new Object[]{this.apiUrl, this.login, e, e}); + if (logger.isLoggable(Level.FINE)) + logger.log(Level.FINE, "Exception validating credentials on " + this.apiUrl + " with login '" + this.login + "' " + e, e); return false; } } diff --git a/src/main/java/org/kohsuke/github/HttpException.java b/src/main/java/org/kohsuke/github/HttpException.java index 37c16f4a12..718642299d 100644 --- a/src/main/java/org/kohsuke/github/HttpException.java +++ b/src/main/java/org/kohsuke/github/HttpException.java @@ -4,8 +4,12 @@ import java.net.HttpURLConnection; import java.net.URL; +import javax.annotation.CheckForNull; + /** - * Http exception + * {@link IOException} for http exceptions because {@link HttpURLConnection} throws un-discerned + * {@link IOException} and it can help to know the http response code to decide how to handle an + * http exceptions. * * @author Cyrille Le Clerc */ @@ -81,7 +85,7 @@ public HttpException(int responseCode, String responseMessage, String url, Throw * @see HttpURLConnection#getResponseCode() * @see HttpURLConnection#getResponseMessage() */ - public HttpException(int responseCode, String responseMessage, URL url, Throwable cause) { + public HttpException(int responseCode, String responseMessage, @CheckForNull URL url, Throwable cause) { this(responseCode, responseMessage, url == null ? null : url.toString(), cause); } @@ -111,9 +115,4 @@ public String getResponseMessage() { public String getUrl() { return url; } - - @Override - public String getMessage() { - return super.getMessage(); - } } diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index 4670b00a8e..6ac2a084c2 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -48,6 +48,8 @@ import java.util.Locale; import java.util.Map; import java.util.NoSuchElementException; +import java.util.logging.Level; +import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.GZIPInputStream; @@ -64,7 +66,9 @@ */ class Requester { private static final List METHODS_WITHOUT_BODY = asList("GET", "DELETE"); - + + protected final transient Logger logger = Logger.getLogger(getClass().getName()); + private final GitHub root; private final List args = new ArrayList(); private final Map headers = new LinkedHashMap(); @@ -526,6 +530,9 @@ private InputStream wrapStream(InputStream in) throws IOException { } catch (IOException e2) { // likely to be a network exception (e.g. SSLHandshakeException), // uc.getResponseCode() and any other getter on the response will cause an exception + if (logger.isLoggable(Level.FINE)) + logger.log(Level.FINE, "Silently ignore exception retrieving response code for '" + uc.getURL() + "'" + + " handling exception " + e, e); throw e; } if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) // 401 / Unauthorized == bad creds From e09185fd0eb92d464ee44ce845db26dd889a5677 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 11 Mar 2016 22:51:48 -0800 Subject: [PATCH 101/390] Logger should be static --- src/main/java/org/kohsuke/github/GitHub.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 850edaf531..4ac80c9942 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -25,13 +25,13 @@ import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.ANY; import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE; +import static java.util.logging.Level.FINE; import java.io.ByteArrayInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; -import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.text.ParseException; @@ -56,7 +56,6 @@ import com.fasterxml.jackson.databind.introspect.VisibilityChecker.Std; import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import java.nio.charset.Charset; -import java.util.logging.Level; import java.util.logging.Logger; /** @@ -71,8 +70,6 @@ * @author Kohsuke Kawaguchi */ public class GitHub { - protected final transient Logger logger = Logger.getLogger(getClass().getName()); - /*package*/ final String login; /** @@ -463,8 +460,8 @@ public boolean isCredentialValid() throws IOException { retrieve().to("/user", GHUser.class); return true; } catch (IOException e) { - if (logger.isLoggable(Level.FINE)) - logger.log(Level.FINE, "Exception validating credentials on " + this.apiUrl + " with login '" + this.login + "' " + e, e); + if (LOGGER.isLoggable(FINE)) + LOGGER.log(FINE, "Exception validating credentials on " + this.apiUrl + " with login '" + this.login + "' " + e, e); return false; } } @@ -611,4 +608,6 @@ public Reader renderMarkdown(String text) throws IOException { } /* package */ static final String GITHUB_URL = "https://api.github.com"; + + private static final Logger LOGGER = Logger.getLogger(GitHub.class.getName()); } From ae49166aa2f162a1e65322641ccc8247e6ca9a5b Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 11 Mar 2016 22:55:44 -0800 Subject: [PATCH 102/390] No such parameter exists on this method --- src/main/java/org/kohsuke/github/HttpException.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/HttpException.java b/src/main/java/org/kohsuke/github/HttpException.java index 718642299d..670cb491f4 100644 --- a/src/main/java/org/kohsuke/github/HttpException.java +++ b/src/main/java/org/kohsuke/github/HttpException.java @@ -56,8 +56,6 @@ public HttpException(String message, int responseCode, String responseMessage, S } /** - * @param message The detail message (which is saved for later retrieval - * by the {@link #getMessage()} method) * @param responseCode Http response code. {@code -1} if no code can be discerned. * @param responseMessage Http response message * @param url The url that was invoked From dba84a33b9702b0fde265dad9bdb3bec897a5ce0 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 11 Mar 2016 22:55:58 -0800 Subject: [PATCH 103/390] Logger should be static --- src/main/java/org/kohsuke/github/Requester.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index 6ac2a084c2..311b3320b4 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -48,7 +48,6 @@ import java.util.Locale; import java.util.Map; import java.util.NoSuchElementException; -import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -57,6 +56,7 @@ import javax.annotation.WillClose; import static java.util.Arrays.asList; +import static java.util.logging.Level.FINE; import static org.kohsuke.github.GitHub.*; /** @@ -65,10 +65,6 @@ * @author Kohsuke Kawaguchi */ class Requester { - private static final List METHODS_WITHOUT_BODY = asList("GET", "DELETE"); - - protected final transient Logger logger = Logger.getLogger(getClass().getName()); - private final GitHub root; private final List args = new ArrayList(); private final Map headers = new LinkedHashMap(); @@ -530,8 +526,8 @@ private InputStream wrapStream(InputStream in) throws IOException { } catch (IOException e2) { // likely to be a network exception (e.g. SSLHandshakeException), // uc.getResponseCode() and any other getter on the response will cause an exception - if (logger.isLoggable(Level.FINE)) - logger.log(Level.FINE, "Silently ignore exception retrieving response code for '" + uc.getURL() + "'" + + if (LOGGER.isLoggable(FINE)) + LOGGER.log(FINE, "Silently ignore exception retrieving response code for '" + uc.getURL() + "'" + " handling exception " + e, e); throw e; } @@ -557,4 +553,7 @@ private InputStream wrapStream(InputStream in) throws IOException { IOUtils.closeQuietly(es); } } + + private static final List METHODS_WITHOUT_BODY = asList("GET", "DELETE"); + private static final Logger LOGGER = Logger.getLogger(Requester.class.getName()); } From cd8d9556468475e8ed6108a6499f4cd119a0a899 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 11 Mar 2016 23:06:21 -0800 Subject: [PATCH 104/390] Documenting what one gets --- src/main/java/org/kohsuke/github/GitHub.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 14e7b13368..10bb3ea090 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -502,6 +502,25 @@ public void checkApiUrlValidity() throws IOException { private boolean isPrivateModeEnabled() { try { HttpURLConnection connect = getConnector().connect(getApiURL("/")); + /* + $ curl -i https://github.mycompany.com/api/v3/ + HTTP/1.1 401 Unauthorized + Server: GitHub.com + Date: Sat, 05 Mar 2016 19:45:01 GMT + Content-Type: application/json; charset=utf-8 + Content-Length: 130 + Status: 401 Unauthorized + X-GitHub-Media-Type: github.v3 + X-XSS-Protection: 1; mode=block + X-Frame-Options: deny + Content-Security-Policy: default-src 'none' + Access-Control-Allow-Credentials: true + Access-Control-Expose-Headers: ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval + Access-Control-Allow-Origin: * + X-GitHub-Request-Id: dbc70361-b11d-4131-9a7f-674b8edd0411 + Strict-Transport-Security: max-age=31536000; includeSubdomains; preload + X-Content-Type-Options: nosniff + */ if (connect.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED && connect.getHeaderField("Server") != null && connect.getHeaderField("Server").equals("GitHub.com")) { From 10f55cc54926ab47da73da6d54dc3dd52f397add Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 11 Mar 2016 23:10:41 -0800 Subject: [PATCH 105/390] Checking another header I think it's better to pick a header that's unique to GitHub. --- src/main/java/org/kohsuke/github/GitHub.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 10bb3ea090..b8673e4533 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -25,6 +25,7 @@ import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.ANY; import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE; +import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; import java.io.ByteArrayInputStream; import java.io.FileNotFoundException; @@ -501,7 +502,7 @@ public void checkApiUrlValidity() throws IOException { */ private boolean isPrivateModeEnabled() { try { - HttpURLConnection connect = getConnector().connect(getApiURL("/")); + HttpURLConnection uc = getConnector().connect(getApiURL("/")); /* $ curl -i https://github.mycompany.com/api/v3/ HTTP/1.1 401 Unauthorized @@ -521,12 +522,8 @@ private boolean isPrivateModeEnabled() { Strict-Transport-Security: max-age=31536000; includeSubdomains; preload X-Content-Type-Options: nosniff */ - if (connect.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED - && connect.getHeaderField("Server") != null - && connect.getHeaderField("Server").equals("GitHub.com")) { - return true; - } - return false; + return uc.getResponseCode() == HTTP_UNAUTHORIZED + && uc.getHeaderField("X-GitHub-Media-Type") != null; } catch (IOException e) { return false; } From 3b764f9c9081df2a93922603506f5df976394182 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 11 Mar 2016 23:11:22 -0800 Subject: [PATCH 106/390] Don't lose the original problem --- src/main/java/org/kohsuke/github/GitHub.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index b8673e4533..cb94f1076e 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -486,11 +486,11 @@ void check(String apiUrl) throws IOException { public void checkApiUrlValidity() throws IOException { try { retrieve().to("/", GHApiInfo.class).check(apiUrl); - } catch (IOException ioe) { + } catch (IOException e) { if (isPrivateModeEnabled()) { - throw new IOException("GitHub Enterprise server (" + apiUrl + ") with private mode enabled"); + throw (IOException)new IOException("GitHub Enterprise server (" + apiUrl + ") with private mode enabled").initCause(e); } - throw ioe; + throw e; } } From 1954a9f3f8d998ad6a349c044960a33cd24bfd9a Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 11 Mar 2016 23:12:50 -0800 Subject: [PATCH 107/390] This isn't just about API URL but it also checks the valid credential --- src/main/java/org/kohsuke/github/GitHub.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index cb94f1076e..7aa928e782 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -477,7 +477,10 @@ void check(String apiUrl) throws IOException { } /** - * Ensures that the API URL is valid. + * Tests the connection. + * + *

+ * Verify that the API URL and credentials are valid to access this GitHub. * *

* This method returns normally if the endpoint is reachable and verified to be GitHub API URL. From 7a78f9f5aac0d35d07cc7d958fe5d7ba8a5440ff Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 11 Mar 2016 23:14:40 -0800 Subject: [PATCH 108/390] No need to require 1.6 --- pom.xml | 8 -------- src/main/java/org/kohsuke/github/HttpException.java | 6 ++++-- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/pom.xml b/pom.xml index dde789075d..0af43488f1 100644 --- a/pom.xml +++ b/pom.xml @@ -46,14 +46,6 @@ - - org.apache.maven.plugins - maven-compiler-plugin - - 1.6 - 1.6 - - org.codehaus.mojo findbugs-maven-plugin diff --git a/src/main/java/org/kohsuke/github/HttpException.java b/src/main/java/org/kohsuke/github/HttpException.java index 670cb491f4..16c8e68be2 100644 --- a/src/main/java/org/kohsuke/github/HttpException.java +++ b/src/main/java/org/kohsuke/github/HttpException.java @@ -49,7 +49,8 @@ public HttpException(String message, int responseCode, String responseMessage, S * @see HttpURLConnection#getResponseMessage() */ public HttpException(String message, int responseCode, String responseMessage, String url, Throwable cause) { - super(message, cause); + super(message); + initCause(cause); this.responseCode = responseCode; this.responseMessage = responseMessage; this.url = url; @@ -67,7 +68,8 @@ public HttpException(String message, int responseCode, String responseMessage, S */ public HttpException(int responseCode, String responseMessage, String url, Throwable cause) { super("Server returned HTTP response code: " + responseCode + ", message: '" + responseMessage + "'" + - " for URL: " + url, cause); + " for URL: " + url); + initCause(cause); this.responseCode = responseCode; this.responseMessage = responseMessage; this.url = url; From c1c2a2735895622fafe69003c015a7b8a4285f50 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 11 Mar 2016 23:21:07 -0800 Subject: [PATCH 109/390] Doc improvement --- src/main/java/org/kohsuke/github/GitHubBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GitHubBuilder.java b/src/main/java/org/kohsuke/github/GitHubBuilder.java index 42a0f2be6f..2abe16f9c1 100644 --- a/src/main/java/org/kohsuke/github/GitHubBuilder.java +++ b/src/main/java/org/kohsuke/github/GitHubBuilder.java @@ -15,7 +15,7 @@ import java.util.Properties; /** - * + * Configures connection details and produces {@link GitHub}. * * @since 1.59 */ From 14dcb37ee1ea225b73b548faae313ab512ae69a4 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 11 Mar 2016 23:29:58 -0800 Subject: [PATCH 110/390] Not all caller wants GET --- src/main/java/org/kohsuke/github/GHContent.java | 3 ++- src/main/java/org/kohsuke/github/Requester.java | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHContent.java b/src/main/java/org/kohsuke/github/GHContent.java index 8955505219..88a5517364 100644 --- a/src/main/java/org/kohsuke/github/GHContent.java +++ b/src/main/java/org/kohsuke/github/GHContent.java @@ -115,7 +115,8 @@ public String getHtmlUrl() { * Retrieves the actual content stored here. */ public InputStream read() throws IOException { - return new Requester(root).asStream(getDownloadUrl()); + // if the download link is encoded with a token on the query string, the default behavior of POST will fail + return new Requester(root).method("GET").asStream(getDownloadUrl()); } /** diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index b305787596..4a9bf67ee7 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -284,7 +284,6 @@ public int asHttpStatusCode(String tailApiUrl) throws IOException { public InputStream asStream(String tailApiUrl) throws IOException { while (true) {// loop while API rate limit is hit - method("GET"); // if the download link is encoded with a token on the query string, the default behavior of POST will fail setupConnection(root.getApiURL(tailApiUrl)); buildRequest(); From 906d9af7b757d6b4da5a7b6f15eb60bafe490120 Mon Sep 17 00:00:00 2001 From: Ruben Dijkstra Date: Sat, 12 Mar 2016 21:48:50 +0100 Subject: [PATCH 111/390] Include the animal sniffer plugin 7a78f9f5aac0d35d07cc7d958fe5d7ba8a5440ff set the compiler level back to 5, but there are no guarantees that we don't accidentally use any features from newer class libraries. --- pom.xml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/pom.xml b/pom.xml index 0af43488f1..63ff3acb00 100644 --- a/pom.xml +++ b/pom.xml @@ -34,6 +34,27 @@ + + org.codehaus.mojo + animal-sniffer-maven-plugin + 1.15 + + + org.codehaus.mojo.signature + java15 + 1.0 + + + + + ensure-java-1.5-class-library + test + + check + + + + com.infradna.tool bridge-method-injector From 755d5f77ea0d990184d1068b5bcb450380b9d7d1 Mon Sep 17 00:00:00 2001 From: Ruben Dijkstra Date: Sat, 12 Mar 2016 21:56:56 +0100 Subject: [PATCH 112/390] Java 5 doesn't have Arrays.copyOf() http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Arrays.html --- src/main/java/org/kohsuke/github/GHCompare.java | 10 ++++++---- .../org/kohsuke/github/GHPullRequestCommitDetail.java | 5 +++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHCompare.java b/src/main/java/org/kohsuke/github/GHCompare.java index c9c882ba4e..100753db01 100644 --- a/src/main/java/org/kohsuke/github/GHCompare.java +++ b/src/main/java/org/kohsuke/github/GHCompare.java @@ -4,8 +4,6 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.net.URL; -import java.util.Arrays; -import java.util.Date; /** * The model user for comparing 2 commits in the GitHub API. @@ -72,7 +70,9 @@ public Commit getMergeBaseCommit() { * @return A copy of the array being stored in the class. */ public Commit[] getCommits() { - return Arrays.copyOf(commits, commits.length); + Commit[] newValue = new Commit[commits.length]; + System.arraycopy(commits, 0, newValue, 0, commits.length); + return newValue; } /** @@ -80,7 +80,9 @@ public Commit[] getCommits() { * @return A copy of the array being stored in the class. */ public GHCommit.File[] getFiles() { - return Arrays.copyOf(files, files.length); + GHCommit.File[] newValue = new GHCommit.File[files.length]; + System.arraycopy(files, 0, newValue, 0, files.length); + return newValue; } public GHCompare wrap(GHRepository owner) { diff --git a/src/main/java/org/kohsuke/github/GHPullRequestCommitDetail.java b/src/main/java/org/kohsuke/github/GHPullRequestCommitDetail.java index d4b48da538..e6c558b9e1 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestCommitDetail.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestCommitDetail.java @@ -27,7 +27,6 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.net.URL; -import java.util.Arrays; /** * Commit detail inside a {@link GHPullRequest}. @@ -144,6 +143,8 @@ public URL getCommentsUrl() { } public CommitPointer[] getParents() { - return Arrays.copyOf(parents, parents.length); + CommitPointer[] newValue = new CommitPointer[parents.length]; + System.arraycopy(parents, 0, newValue, 0, parents.length); + return newValue; } } From f9014dbab36bd8b48275ab49c127b6132d32969c Mon Sep 17 00:00:00 2001 From: Ruben Dijkstra Date: Sat, 12 Mar 2016 21:58:27 +0100 Subject: [PATCH 113/390] Convert to legacy Throwable.initCause() --- src/main/java/org/kohsuke/github/GHRepository.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index fbd64709a6..c74d9095aa 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -1152,7 +1152,7 @@ public GHContentUpdateResponse createContent(String content, String commitMessag try { payload = content.getBytes("UTF-8"); } catch (UnsupportedEncodingException ex) { - throw new IOException("UTF-8 encoding is not supported", ex); + throw (IOException) new IOException("UTF-8 encoding is not supported").initCause(ex); } return createContent(payload, commitMessage, path, branch); } From 36d5b092d77660ab0d7b59f6f94ca37ba6f76d1a Mon Sep 17 00:00:00 2001 From: Ruben Dijkstra Date: Sat, 12 Mar 2016 21:59:51 +0100 Subject: [PATCH 114/390] Java 5 doesn't have new String(byte[], Charset) http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/String.html --- src/main/java/org/kohsuke/github/GitHub.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index d957212b2b..6180f768b1 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -57,7 +57,6 @@ 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; import java.util.logging.Logger; /** @@ -134,8 +133,8 @@ public class GitHub { } else { if (password!=null) { String authorization = (login + ':' + password); - Charset charset = Charsets.UTF_8; - encodedAuthorization = "Basic "+new String(Base64.encodeBase64(authorization.getBytes(charset)), charset); + String charsetName = Charsets.UTF_8.name(); + encodedAuthorization = "Basic "+new String(Base64.encodeBase64(authorization.getBytes(charsetName)), charsetName); } else {// anonymous access encodedAuthorization = null; } From 0cd5147e1ab2c4549c817db340d94bcdf51d02d3 Mon Sep 17 00:00:00 2001 From: Ruben Dijkstra Date: Sat, 12 Mar 2016 22:01:25 +0100 Subject: [PATCH 115/390] Java 5 doesn't have TimeUnit.HOURS http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/TimeUnit.html --- src/main/java/org/kohsuke/github/GitHub.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 6180f768b1..22792a8798 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -48,7 +48,6 @@ import java.util.Map; import java.util.Set; import java.util.TimeZone; -import java.util.concurrent.TimeUnit; import org.apache.commons.codec.Charsets; import org.apache.commons.codec.binary.Base64; @@ -264,7 +263,8 @@ public GHRateLimit getRateLimit() throws IOException { // see issue #78 GHRateLimit r = new GHRateLimit(); r.limit = r.remaining = 1000000; - r.reset = new Date(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(1)); + long hours = 1000L * 60 * 60; + r.reset = new Date(System.currentTimeMillis() + 1 * hours ); return r; } } From 397886d289cd4e2c1a5acabb7b2397c907d484be Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 18 Mar 2016 19:08:51 -0700 Subject: [PATCH 116/390] Excluding a flaky test --- src/test/java/org/kohsuke/github/GHContentIntegrationTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/org/kohsuke/github/GHContentIntegrationTest.java b/src/test/java/org/kohsuke/github/GHContentIntegrationTest.java index 7848143a86..8e3873708b 100644 --- a/src/test/java/org/kohsuke/github/GHContentIntegrationTest.java +++ b/src/test/java/org/kohsuke/github/GHContentIntegrationTest.java @@ -66,7 +66,8 @@ public void testCRUDContent() throws Exception { assertNotNull(updatedContentResponse.getCommit()); assertNotNull(updatedContentResponse.getContent()); - assertEquals("this is some new content\n", updatedContent.getContent()); + // due to what appears to be a cache propagation delay, this test is too flaky + // assertEquals("this is some new content\n", updatedContent.getContent()); GHContentUpdateResponse deleteResponse = updatedContent.delete("Enough of this foolishness!"); From a31395ed806aed032243672d3e4f1d796cefadd9 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 18 Mar 2016 19:15:52 -0700 Subject: [PATCH 117/390] Signature fix for Java5 --- .../java/org/kohsuke/github/GHContent.java | 4 ++-- .../java/org/kohsuke/github/GHRepository.java | 18 +++++++++++++++--- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHContent.java b/src/main/java/org/kohsuke/github/GHContent.java index 88a5517364..8b6f6fea54 100644 --- a/src/main/java/org/kohsuke/github/GHContent.java +++ b/src/main/java/org/kohsuke/github/GHContent.java @@ -78,7 +78,7 @@ public String getPath() { */ @SuppressFBWarnings("DM_DEFAULT_ENCODING") public String getContent() throws IOException { - return new String(DatatypeConverter.parseBase64Binary(getEncodedContent())); + return new String(Base64.decodeBase64(getEncodedContent())); } /** @@ -179,7 +179,7 @@ public GHContentUpdateResponse update(byte[] newContentBytes, String commitMessa } public GHContentUpdateResponse update(byte[] newContentBytes, String commitMessage, String branch) throws IOException { - String encodedContent = DatatypeConverter.printBase64Binary(newContentBytes); + String encodedContent = Base64.encodeBase64String(newContentBytes); Requester requester = new Requester(root) .with("path", path) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index c74d9095aa..326564e521 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -26,9 +26,9 @@ 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.codec.binary.Base64; import org.apache.commons.lang.StringUtils; -import javax.xml.bind.DatatypeConverter; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; @@ -36,7 +36,19 @@ import java.io.Reader; import java.io.UnsupportedEncodingException; import java.net.URL; -import java.util.*; +import java.util.AbstractSet; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; import static java.util.Arrays.asList; @@ -1165,7 +1177,7 @@ public GHContentUpdateResponse createContent(byte[] contentBytes, String commitM Requester requester = new Requester(root) .with("path", path) .with("message", commitMessage) - .with("content", DatatypeConverter.printBase64Binary(contentBytes)) + .with("content", Base64.encodeBase64String(contentBytes)) .method("PUT"); if (branch != null) { From 557ae4165c05b7c37d09e93ac5025cdae6b1db7b Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 18 Mar 2016 19:19:51 -0700 Subject: [PATCH 118/390] Not important --- src/main/java/org/kohsuke/github/Requester.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index 4a9bf67ee7..8f922b4ff3 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -24,6 +24,7 @@ package org.kohsuke.github; import com.fasterxml.jackson.databind.JsonMappingException; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.apache.commons.io.IOUtils; import java.io.FileNotFoundException; @@ -138,7 +139,7 @@ public Requester with(String key, Enum e) { // by convention Java constant names are upper cases, but github uses // lower-case constants. GitHub also uses '-', which in Java we always // replace by '_' - return with(key, e.toString().toLowerCase(Locale.ENGLISH).replace('_','-')); + return with(key, e.toString().toLowerCase(Locale.ENGLISH).replace('_', '-')); } public Requester with(String key, String value) { @@ -216,9 +217,10 @@ public T to(String tailApiUrl, T existingInstance) throws IOException { */ @Deprecated public T to(String tailApiUrl, Class type, String method) throws IOException { - return method(method).to(tailApiUrl,type); + return method(method).to(tailApiUrl, type); } + @SuppressFBWarnings("SBSC_USE_STRINGBUFFER_CONCATENATION") private T _to(String tailApiUrl, Class type, T instance) throws IOException { if (METHODS_WITHOUT_BODY.contains(method) && !args.isEmpty()) { boolean questionMarkFound = tailApiUrl.indexOf('?') != -1; From 255c9935488c4d64e9869703382e06934d826a8b Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 18 Mar 2016 19:22:34 -0700 Subject: [PATCH 119/390] [maven-release-plugin] prepare release github-api-1.74 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 63ff3acb00..af07ce2d59 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.74-SNAPSHOT + 1.74 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - HEAD + github-api-1.74 From d30b0403ceb06c71dc9b099352fb9f03045772aa Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 18 Mar 2016 19:22:37 -0700 Subject: [PATCH 120/390] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index af07ce2d59..97139fb438 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.74 + 1.75-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - github-api-1.74 + HEAD From ce140460af99ad73da3136f7a9343f61e5f2129b Mon Sep 17 00:00:00 2001 From: Marcin Zajaczkowski Date: Mon, 4 Apr 2016 17:30:48 +0200 Subject: [PATCH 121/390] [#269] Add reopen method on GHMilestone --- src/main/java/org/kohsuke/github/GHMilestone.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHMilestone.java b/src/main/java/org/kohsuke/github/GHMilestone.java index 0d1b43224e..48f8364bbf 100644 --- a/src/main/java/org/kohsuke/github/GHMilestone.java +++ b/src/main/java/org/kohsuke/github/GHMilestone.java @@ -72,12 +72,19 @@ public GHMilestoneState getState() { } /** - * Closes this issue. + * Closes this milestone. */ public void close() throws IOException { edit("state", "closed"); } + /** + * Reopens this milestone. + */ + public void reopen() throws IOException { + edit("state", "open"); + } + private void edit(String key, Object value) throws IOException { new Requester(root)._with(key, value).method("PATCH").to(getApiRoute()); } From 715192d26cca81fe118e91f36c53109068011fce Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 13 Apr 2016 13:07:58 -0700 Subject: [PATCH 122/390] [maven-release-plugin] prepare release github-api-1.75 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 97139fb438..399b8b56e4 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.75-SNAPSHOT + 1.75 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - HEAD + github-api-1.75 From 6b5ade3ca09bb53a5880dc227fd187fc51299f7c Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 13 Apr 2016 13:08:02 -0700 Subject: [PATCH 123/390] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 399b8b56e4..437851005b 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.75 + 1.76-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - github-api-1.75 + HEAD From beae9fd6ec1b94fd58fd6260a38a8c4eacf333bc Mon Sep 17 00:00:00 2001 From: noctarius Date: Thu, 14 Apr 2016 07:09:05 +0200 Subject: [PATCH 124/390] Added support for the extended stargazers API in Github V3 API --- .../java/org/kohsuke/github/GHRepository.java | 26 +++++++++- .../java/org/kohsuke/github/GHStargazer.java | 48 +++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/kohsuke/github/GHStargazer.java diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 326564e521..26cba13087 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -935,12 +935,36 @@ public PagedIterable listSubscribers() { } /** - * Lists all the users who have starred this repo. + * Lists all the users who have starred this repo based on the old version of the API. For + * additional information, like date when the repository was starred, see {@link #listExtendedStargazers()} */ public PagedIterable listStargazers() { return listUsers("stargazers"); } + /** + * Lists all the users who have starred this repo based on new version of the API, having extended + * information like the time when the repository was starred. For compatibility with the old API + * see {@link #listStargazers()} + */ + public PagedIterable listExtendedStargazers() { + return new PagedIterable() { + @Override + public PagedIterator _iterator(int pageSize) { + Requester requester = root.retrieve(); + requester.setHeader("Accept", "application/vnd.github.v3.star+json"); + return new PagedIterator(requester.asIterator(getApiTailUrl("stargazers"), GHStargazer[].class, pageSize)) { + @Override + protected void wrapUp(GHStargazer[] page) { + for (GHStargazer c : page) { + c.wrapUp(GHRepository.this); + } + } + }; + } + }; + } + private PagedIterable listUsers(final String suffix) { return new PagedIterable() { public PagedIterator _iterator(int pageSize) { diff --git a/src/main/java/org/kohsuke/github/GHStargazer.java b/src/main/java/org/kohsuke/github/GHStargazer.java new file mode 100644 index 0000000000..20b3ef8a7d --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHStargazer.java @@ -0,0 +1,48 @@ +package org.kohsuke.github; + +import java.util.Date; + +/** + * A stargazer at a repository on GitHub. + * + * @author noctarius + */ +public class GHStargazer { + + private GHRepository repository; + private String starred_at; + private GHUser user; + + /** + * Gets the repository that is stargazed + * + * @return the starred repository + */ + public GHRepository getRepository() { + return repository; + } + + /** + * Gets the date when the repository was starred, however old stars before + * August 2012, will all show the date the API was changed to support starred_at. + * + * @return the date the stargazer was added + */ + public Date getStarredAt() { + return GitHub.parseDate(starred_at); + } + + /** + * Gets the user that starred the repository + * + * @return the stargazer user + */ + public GHUser getUser() { + return user; + } + + void wrapUp(GHRepository repository) { + this.repository = repository; + user.wrapUp(repository.root); + } +} From 007378c3a6f4d8ea87abd1dfd6a7f8cfc9feac80 Mon Sep 17 00:00:00 2001 From: thug-gamer Date: Fri, 29 Apr 2016 11:41:14 +0200 Subject: [PATCH 125/390] Add support to delete a team Add a method to delete a team. --- src/main/java/org/kohsuke/github/GHTeam.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHTeam.java b/src/main/java/org/kohsuke/github/GHTeam.java index cf7dd1fc91..76555f6da7 100644 --- a/src/main/java/org/kohsuke/github/GHTeam.java +++ b/src/main/java/org/kohsuke/github/GHTeam.java @@ -126,6 +126,13 @@ public void add(GHRepository r) throws IOException { public void remove(GHRepository r) throws IOException { org.root.retrieve().method("DELETE").to(api("/repos/" + r.getOwnerName() + '/' + r.getName()), null); } + + /** + * Deletes this team. + */ + public void delete() throws IOException { + org.root.retrieve().method("DELETE").to(api("")); + } private String api(String tail) { return "/teams/"+id+tail; From baedad81240b75334a7ddf138a015ef6207de76b Mon Sep 17 00:00:00 2001 From: Konda Reddy Date: Sat, 30 Apr 2016 13:20:44 -0500 Subject: [PATCH 126/390] Updated Date was wrong --- src/main/java/org/kohsuke/github/GHPerson.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHPerson.java b/src/main/java/org/kohsuke/github/GHPerson.java index e9a750f2cc..ef93dd75aa 100644 --- a/src/main/java/org/kohsuke/github/GHPerson.java +++ b/src/main/java/org/kohsuke/github/GHPerson.java @@ -204,7 +204,7 @@ public Date getCreatedAt() throws IOException { public Date getUpdatedAt() throws IOException { populate(); - return super.getCreatedAt(); + return super.getUpdatedAt(); } /** From 35dec7a5ec3d1a8174176356e62b81746e085b7f Mon Sep 17 00:00:00 2001 From: Jesse Glick Date: Tue, 3 May 2016 18:19:57 -0400 Subject: [PATCH 127/390] Fixed broken link. --- src/main/java/org/kohsuke/github/GHEvent.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHEvent.java b/src/main/java/org/kohsuke/github/GHEvent.java index e8e79bb456..b33cb991eb 100644 --- a/src/main/java/org/kohsuke/github/GHEvent.java +++ b/src/main/java/org/kohsuke/github/GHEvent.java @@ -5,10 +5,9 @@ /** * Hook event type. * - * See http://developer.github.com/v3/events/types/ - * * @author Kohsuke Kawaguchi * @see GHEventInfo + * @see Event type reference */ public enum GHEvent { COMMIT_COMMENT, From d530b34073d575261974104ddb435798e5fb6b98 Mon Sep 17 00:00:00 2001 From: Andy Pemberton Date: Sat, 14 May 2016 08:58:42 -0400 Subject: [PATCH 128/390] Add Slug to GHTeam per v3 API: https://developer.github.com/v3/orgs/teams/ --- src/main/java/org/kohsuke/github/GHOrganization.java | 11 +++++++++++ src/main/java/org/kohsuke/github/GHTeam.java | 6 +++++- src/test/java/org/kohsuke/github/AppTest.java | 7 +++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHOrganization.java b/src/main/java/org/kohsuke/github/GHOrganization.java index c4ae92e6db..0c62fd8a2a 100644 --- a/src/main/java/org/kohsuke/github/GHOrganization.java +++ b/src/main/java/org/kohsuke/github/GHOrganization.java @@ -93,6 +93,17 @@ public GHTeam getTeamByName(String name) throws IOException { return null; } + /** + * Finds a team that has the given slug in its {@link GHTeam#getSlug()} + */ + public GHTeam getTeamBySlug(String slug) throws IOException { + for (GHTeam t : listTeams()) { + if(t.getSlug().equals(slug)) + return t; + } + return null; + } + /** * Checks if this organization has the specified user as a member. */ diff --git a/src/main/java/org/kohsuke/github/GHTeam.java b/src/main/java/org/kohsuke/github/GHTeam.java index cf7dd1fc91..e0cd33b8bd 100644 --- a/src/main/java/org/kohsuke/github/GHTeam.java +++ b/src/main/java/org/kohsuke/github/GHTeam.java @@ -12,7 +12,7 @@ * @author Kohsuke Kawaguchi */ public class GHTeam { - private String name,permission; + private String name,permission,slug; private int id; private GHOrganization organization; // populated by GET /user/teams where Teams+Orgs are returned together @@ -43,6 +43,10 @@ public String getPermission() { return permission; } + public String getSlug() { + return slug; + } + public int getId() { return id; } diff --git a/src/test/java/org/kohsuke/github/AppTest.java b/src/test/java/org/kohsuke/github/AppTest.java index c8d523cd81..905818981b 100755 --- a/src/test/java/org/kohsuke/github/AppTest.java +++ b/src/test/java/org/kohsuke/github/AppTest.java @@ -335,6 +335,13 @@ public void testOrgTeamByName() throws Exception { assertNotNull(e); } + @Test + public void testOrgTeamBySlug() throws Exception { + kohsuke(); + GHTeam e = gitHub.getOrganization("github-api-test-org").getTeamBySlug("core-developers"); + assertNotNull(e); + } + @Test public void testCommit() throws Exception { GHCommit commit = gitHub.getUser("jenkinsci").getRepository("jenkins").getCommit("08c1c9970af4d609ae754fbe803e06186e3206f7"); From 5f95987a487491aa9b1584051b3304c171d32bce Mon Sep 17 00:00:00 2001 From: Andy Pemberton Date: Sat, 14 May 2016 20:07:04 -0400 Subject: [PATCH 129/390] related to JENKINS-34834. updating test for similar condition --- src/test/java/org/kohsuke/github/AppTest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/kohsuke/github/AppTest.java b/src/test/java/org/kohsuke/github/AppTest.java index c8d523cd81..06ddabf443 100755 --- a/src/test/java/org/kohsuke/github/AppTest.java +++ b/src/test/java/org/kohsuke/github/AppTest.java @@ -221,10 +221,12 @@ public void testMyOrganizations() throws IOException { } @Test - public void testMyTeamsContainsAllMyOrganizations() throws IOException { + public void testMyOrganizationsContainMyTeams() throws IOException { Map> teams = gitHub.getMyTeams(); Map myOrganizations = gitHub.getMyOrganizations(); - assertEquals(teams.keySet(), myOrganizations.keySet()); + //GitHub no longer has default 'owners' team, so there may be organization memberships without a team + //https://help.github.com/articles/about-improved-organization-permissions/ + assertTrue(myOrganizations.keySet().containsAll(teams.keySet())); } @Test From 3c5592c1c8e77341a3c24213e779a464b77228c0 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Thu, 2 Jun 2016 22:05:24 -0700 Subject: [PATCH 130/390] Following the convention with GHMyself.getEmails2() This way the method is more discoverable with IDE auto-completion --- src/main/java/org/kohsuke/github/GHRepository.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 26cba13087..3e7962b566 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -936,7 +936,7 @@ public PagedIterable listSubscribers() { /** * Lists all the users who have starred this repo based on the old version of the API. For - * additional information, like date when the repository was starred, see {@link #listExtendedStargazers()} + * additional information, like date when the repository was starred, see {@link #listStargazers2()} */ public PagedIterable listStargazers() { return listUsers("stargazers"); @@ -947,7 +947,7 @@ public PagedIterable listStargazers() { * information like the time when the repository was starred. For compatibility with the old API * see {@link #listStargazers()} */ - public PagedIterable listExtendedStargazers() { + public PagedIterable listStargazers2() { return new PagedIterable() { @Override public PagedIterator _iterator(int pageSize) { From cde501af8de9b871dc53e656aac6b4bd22196dcb Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Thu, 2 Jun 2016 22:36:47 -0700 Subject: [PATCH 131/390] More meaningful toString() method Produce toString without dilligently adding it to every single class. Rely on heuristics to cut down the number of fields to show. --- src/main/java/org/kohsuke/github/GHIssue.java | 1 + .../java/org/kohsuke/github/GHObject.java | 40 +++++++++++++++++++ .../java/org/kohsuke/github/GHRepository.java | 8 +--- src/main/java/org/kohsuke/github/GHUser.java | 5 --- .../org/kohsuke/github/SkipFromToString.java | 16 ++++++++ src/test/java/org/kohsuke/github/AppTest.java | 13 ++++++ 6 files changed, 72 insertions(+), 11 deletions(-) create mode 100644 src/main/java/org/kohsuke/github/SkipFromToString.java diff --git a/src/main/java/org/kohsuke/github/GHIssue.java b/src/main/java/org/kohsuke/github/GHIssue.java index 39e5c24b70..a5afad6d2e 100644 --- a/src/main/java/org/kohsuke/github/GHIssue.java +++ b/src/main/java/org/kohsuke/github/GHIssue.java @@ -54,6 +54,7 @@ public class GHIssue extends GHObject { protected int number; protected String closed_at; protected int comments; + @SkipFromToString protected String body; // for backward compatibility with < 1.63, this collection needs to hold instances of Label, not GHLabel protected List

+ * Any exception thrown from this method will cause the request to fail, and the caller of github-api + * will receive an exception. If this method returns normally, another request will be attempted. + * For that to make sense, the implementation needs to wait for some time. + * + * @see API documentation from GitHub + * @param e + * Exception from Java I/O layer. If you decide to fail the processing, you can throw + * this exception (or wrap this exception into another exception and throw it.) + * @param uc + * Connection that resulted in an error. Useful for accessing other response headers. + */ + public abstract void onError(IOException e, HttpURLConnection uc) throws IOException; + + /** + * Wait until the API abuse "wait time" is passed. + */ + public static final AbuseLimitHandler WAIT = new AbuseLimitHandler() { + @Override + public void onError(IOException e, HttpURLConnection uc) throws IOException { + try { + Thread.sleep(parseWaitTime(uc)); + } catch (InterruptedException _) { + throw (InterruptedIOException)new InterruptedIOException().initCause(e); + } + } + + private long parseWaitTime(HttpURLConnection uc) { + String v = uc.getHeaderField("Retry-After"); + if (v==null) return 60 * 1000; // can't tell, return 1 min + + return Math.max(1000, Long.parseLong(v)*1000); + } + }; + + /** + * Fail immediately. + */ + public static final AbuseLimitHandler FAIL = new AbuseLimitHandler() { + @Override + public void onError(IOException e, HttpURLConnection uc) throws IOException { + throw (IOException)new IOException("Abust limit reached").initCause(e); + } + }; +} diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 47388c93f2..297596d87e 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -83,7 +83,7 @@ public class GitHub { private final String apiUrl; /*package*/ final RateLimitHandler rateLimitHandler; - /*package*/ final RateLimitHandler abuseLimitHandler; + /*package*/ final AbuseLimitHandler abuseLimitHandler; private HttpConnector connector = HttpConnector.DEFAULT; @@ -123,7 +123,7 @@ public class GitHub { * @param connector * HttpConnector to use. Pass null to use default connector. */ - /* package */ GitHub(String apiUrl, String login, String oauthAccessToken, String password, HttpConnector connector, RateLimitHandler rateLimitHandler, RateLimitHandler abuseLimitHandler) throws IOException { + /* package */ GitHub(String apiUrl, String login, String oauthAccessToken, String password, HttpConnector connector, RateLimitHandler rateLimitHandler, AbuseLimitHandler abuseLimitHandler) throws IOException { if (apiUrl.endsWith("/")) apiUrl = apiUrl.substring(0, apiUrl.length()-1); // normalize this.apiUrl = apiUrl; if (null != connector) this.connector = connector; diff --git a/src/main/java/org/kohsuke/github/GitHubBuilder.java b/src/main/java/org/kohsuke/github/GitHubBuilder.java index 9ff603e199..62a99a6272 100644 --- a/src/main/java/org/kohsuke/github/GitHubBuilder.java +++ b/src/main/java/org/kohsuke/github/GitHubBuilder.java @@ -30,7 +30,7 @@ public class GitHubBuilder { private HttpConnector connector; private RateLimitHandler rateLimitHandler = RateLimitHandler.WAIT; - private RateLimitHandler abuseLimitHandler = RateLimitHandler.ABUSE; + private AbuseLimitHandler abuseLimitHandler = AbuseLimitHandler.WAIT; public GitHubBuilder() { } @@ -179,6 +179,10 @@ public GitHubBuilder withRateLimitHandler(RateLimitHandler handler) { this.rateLimitHandler = handler; return this; } + public GitHubBuilder withAbuseLimitHandler(AbuseLimitHandler handler) { + this.abuseLimitHandler = handler; + return this; + } /** * Configures {@linkplain #withConnector(HttpConnector) connector} diff --git a/src/main/java/org/kohsuke/github/RateLimitHandler.java b/src/main/java/org/kohsuke/github/RateLimitHandler.java index 8ff47a5ab4..053fd783e0 100644 --- a/src/main/java/org/kohsuke/github/RateLimitHandler.java +++ b/src/main/java/org/kohsuke/github/RateLimitHandler.java @@ -9,6 +9,7 @@ * * @author Kohsuke Kawaguchi * @see GitHubBuilder#withRateLimitHandler(RateLimitHandler) + * @see AbuseLimitHandler */ public abstract class RateLimitHandler { /** @@ -48,27 +49,6 @@ private long parseWaitTime(HttpURLConnection uc) { return Math.max(10000, Long.parseLong(v)*1000 - System.currentTimeMillis()); } }; - - /** - * Wait until the API abuse "wait time" is passed. - */ - public static final RateLimitHandler ABUSE = new RateLimitHandler() { - @Override - public void onError(IOException e, HttpURLConnection uc) throws IOException { - try { - Thread.sleep(parseWaitTime(uc)); - } catch (InterruptedException _) { - throw (InterruptedIOException)new InterruptedIOException().initCause(e); - } - } - - private long parseWaitTime(HttpURLConnection uc) { - String v = uc.getHeaderField("Retry-After"); - if (v==null) return 60 * 1000; // can't tell, return 1 min - - return Math.max(1000, Long.parseLong(v)*1000); - } - }; /** * Fail immediately. diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index a0d5e27196..43c4e07694 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -572,10 +572,9 @@ private InputStream wrapStream(InputStream in) throws IOException { root.rateLimitHandler.onError(e,uc); return; } - - // Check to see whether we hit a 403, and the Retry-After field is - // available. - if (responseCode == HttpURLConnection.HTTP_FORBIDDEN && + + // Retry-After is not documented but apparently that field exists + if (responseCode == HttpURLConnection.HTTP_FORBIDDEN && uc.getHeaderField("Retry-After") != null) { this.root.abuseLimitHandler.onError(e,uc); return; From d82397a173cb0d576edc0bf02505dcefebac43ae Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 5 Aug 2016 20:00:05 -0700 Subject: [PATCH 150/390] doc fix --- src/main/java/org/kohsuke/github/AbuseLimitHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/AbuseLimitHandler.java b/src/main/java/org/kohsuke/github/AbuseLimitHandler.java index 1a158ee140..4cb6bfe6c5 100644 --- a/src/main/java/org/kohsuke/github/AbuseLimitHandler.java +++ b/src/main/java/org/kohsuke/github/AbuseLimitHandler.java @@ -14,14 +14,14 @@ */ public abstract class AbuseLimitHandler { /** - * Called when the library encounters HTTP error indicating that the API rate limit is reached. + * Called when the library encounters HTTP error indicating that the API abuse limit is reached. * *

* Any exception thrown from this method will cause the request to fail, and the caller of github-api * will receive an exception. If this method returns normally, another request will be attempted. * For that to make sense, the implementation needs to wait for some time. * - * @see API documentation from GitHub + * @see API documentation from GitHub * @param e * Exception from Java I/O layer. If you decide to fail the processing, you can throw * this exception (or wrap this exception into another exception and throw it.) From bb1cecb95bf24577ccebaaf321022caab5605fa2 Mon Sep 17 00:00:00 2001 From: Duncan Dickinson Date: Fri, 5 Aug 2016 20:11:33 -0700 Subject: [PATCH 151/390] PR-284: license API support Had to do git-diff | git-apply to avoid whitespe changes to GHRepository --- .../java/org/kohsuke/github/GHLicense.java | 110 +++++++++ .../org/kohsuke/github/GHLicenseBase.java | 107 +++++++++ .../java/org/kohsuke/github/GHRepository.java | 48 ++++ src/main/java/org/kohsuke/github/GitHub.java | 28 +++ .../github/extras/PreviewHttpConnector.java | 67 ++++++ .../org/kohsuke/github/GHLicenseTest.java | 220 ++++++++++++++++++ 6 files changed, 580 insertions(+) create mode 100644 src/main/java/org/kohsuke/github/GHLicense.java create mode 100644 src/main/java/org/kohsuke/github/GHLicenseBase.java create mode 100644 src/main/java/org/kohsuke/github/extras/PreviewHttpConnector.java create mode 100644 src/test/java/org/kohsuke/github/GHLicenseTest.java diff --git a/src/main/java/org/kohsuke/github/GHLicense.java b/src/main/java/org/kohsuke/github/GHLicense.java new file mode 100644 index 0000000000..baeb6c3d7d --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHLicense.java @@ -0,0 +1,110 @@ +/* + * The MIT License + * + * Copyright (c) 2016, Duncan Dickinson + * + * 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 edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +/** + * The GitHub Preview API's license information + *

+ * WARNING: This uses a PREVIEW API - you must use {@link org.kohsuke.github.extras.PreviewHttpConnector} + * + * @author Duncan Dickinson + * @see GitHub#getLicense(String) + * @see GHRepository#getFullLicense() + * @see https://developer.github.com/v3/licenses/ + */ +@SuppressWarnings({"UnusedDeclaration"}) +@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", + "NP_UNWRITTEN_FIELD"}, justification = "JSON API") +public class GHLicense extends GHLicenseBase { + + protected String html_url, description, category, implementation, body; + + protected List required = new ArrayList(); + protected List permitted = new ArrayList(); + protected List forbidden = new ArrayList(); + + public URL getHtmlUrl() { + return GitHub.parseURL(html_url); + } + + public String getDescription() { + return description; + } + + public String getCategory() { + return category; + } + + public String getImplementation() { + return implementation; + } + + public List getRequired() { + return required; + } + + public List getPermitted() { + return permitted; + } + + public List getForbidden() { + return forbidden; + } + + public String getBody() { + return body; + } + + @Override + public String toString() { + return "GHLicense{" + + "html_url='" + html_url + '\'' + + ", description='" + description + '\'' + + ", category='" + category + '\'' + + ", implementation='" + implementation + '\'' + + ", body='" + body + '\'' + + ", required=" + required + + ", permitted=" + permitted + + ", forbidden=" + forbidden + + ", htmlUrl=" + getHtmlUrl() + + "} " + super.toString(); + } + + @Override + public boolean equals(Object o) { + return super.equals(o); + } + + @Override + public int hashCode() { + return super.hashCode(); + } +} diff --git a/src/main/java/org/kohsuke/github/GHLicenseBase.java b/src/main/java/org/kohsuke/github/GHLicenseBase.java new file mode 100644 index 0000000000..e6c92359d8 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHLicenseBase.java @@ -0,0 +1,107 @@ +/* + * The MIT License + * + * Copyright (c) 2016, Duncan Dickinson + * + * 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 com.infradna.tool.bridge_method_injector.WithBridgeMethods; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + +import java.net.URL; + +/** + * The basic information for GitHub API licenses - as use in a number of + * API calls that only return the basic details + *

+ * WARNING: This uses a PREVIEW API - you must use {@link org.kohsuke.github.extras.PreviewHttpConnector} + * + * @author Duncan Dickinson + * @see https://developer.github.com/v3/licenses/ + * @see GitHub#listLicenses() + * @see GHRepository#getLicense() + * @see GHLicense GHLicense subclass for the more comprehensive listing of properties + */ +@SuppressWarnings({"UnusedDeclaration"}) +@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", + "NP_UNWRITTEN_FIELD"}, justification = "JSON API") +public class GHLicenseBase { + + protected String key, name, url; + protected Boolean featured; + + /** + * @return a mnemonic for the license + */ + public String getKey() { + return key; + } + + /** + * @return the license name + */ + public String getName() { + return name; + } + + /** + * @return API URL of this object. + */ + @WithBridgeMethods(value = String.class, adapterMethod = "urlToString") + public URL getUrl() { + return GitHub.parseURL(url); + } + + /** + * Featured licenses are bold in the new repository drop-down + * + * @return True if the license is featured, false otherwise + */ + public Boolean isFeatured() { + return featured; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof GHLicenseBase)) return false; + + GHLicenseBase that = (GHLicenseBase) o; + + return getUrl().toString().equals(that.getUrl().toString()); + } + + @Override + public int hashCode() { + return getUrl().toString().hashCode(); + } + + @Override + public String toString() { + return "GHLicenseBase{" + + "key='" + key + '\'' + + ", name='" + name + '\'' + + ", url='" + url + '\'' + + ", featured=" + featured + + '}'; + } +} diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 41a44e9dab..0b7424311b 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -65,6 +65,16 @@ public class GHRepository extends GHObject { private String description, homepage, name, full_name; private String html_url; // this is the UI + /* + * The license information makes use of the preview API. + * + * See: https://developer.github.com/v3/licenses/ + */ + /** + * The basic license details as returned from {@link GitHub#getRepository(String)} + */ + private GHLicenseBase license; + private String git_url, ssh_url, clone_url, svn_url, mirror_url; private GHUser owner; // not fully populated. beware. private boolean has_issues, has_wiki, fork, has_downloads; @@ -839,6 +849,44 @@ protected void wrapUp(GHCommitComment[] page) { } }; } + * Gets the basic license details for the repository. + *

+ * This is a preview item and requires you to use {@link org.kohsuke.github.extras.PreviewHttpConnector} + *

+ * Warning: Only returns the basic license details. Use {@link GitHub#getLicense(String)} + * to get the full license information (hint: pass it {@link GHLicenseBase#getKey()}). + * + * @throws IOException as usual but also if you don't use the preview connector + */ + public GHLicenseBase getLicense() { + return license; + } + + /** + * Access the full license details - makes an additional API call + *

+ * This is a preview item and requires you to use {@link org.kohsuke.github.extras.PreviewHttpConnector} + * + * @return the license details + * @throws IOException as usual but also if you don't use the preview connector + */ + public GHLicense getFullLicense() throws IOException { + return root.getLicense(license.getKey()); + } + + /** + * Retrieves the contents of the repository's license file - makes an additional API call + *

+ * This is a preview item and requires you to use {@link org.kohsuke.github.extras.PreviewHttpConnector} + * + * @return details regarding the license contents + * @throws IOException as usual but also if you don't use the preview connector + */ + public GHContent getLicenseContent() throws IOException { + return root.retrieve().to(getApiTailUrl("license"), GHContent.class).wrap(this); + } + + /** /** * Lists all the commit statues attached to the given commit, newer ones first. diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 297596d87e..dd1e3593e3 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -56,6 +56,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.introspect.VisibilityChecker.Std; import com.infradna.tool.bridge_method_injector.WithBridgeMethods; + import java.util.logging.Logger; /** @@ -339,6 +340,33 @@ public GHRepository getRepository(String name) throws IOException { String[] tokens = name.split("/"); return retrieve().to("/repos/" + tokens[0] + '/' + tokens[1], GHRepository.class).wrap(this); } + * Returns a list of popular open source licenses + * + * WARNING: This uses a PREVIEW API - you must use {@link org.kohsuke.github.extras.PreviewHttpConnector} + * + * @see GitHub API - Licenses + * + * @return a list of popular open source licenses + * @throws IOException if the HttpConnector doesn't pass in the preview header or other IO issue + */ + public List listLicenses() throws IOException { + return Arrays.asList(retrieve().to("/licenses", GHLicenseBase[].class)); + } + + /** + * Returns the full details for a license + * + * WARNING: This uses a PREVIEW API - you must use {@link org.kohsuke.github.extras.PreviewHttpConnector} + * + * @param key The license key provided from the API + * @return The license details + * @throws IOException + */ + public GHLicense getLicense(String key) throws IOException { + return retrieve().to("/licenses/" + key, GHLicense.class); + } + + /** /** * This method returns a shallowly populated organizations. diff --git a/src/main/java/org/kohsuke/github/extras/PreviewHttpConnector.java b/src/main/java/org/kohsuke/github/extras/PreviewHttpConnector.java new file mode 100644 index 0000000000..e1be7855f4 --- /dev/null +++ b/src/main/java/org/kohsuke/github/extras/PreviewHttpConnector.java @@ -0,0 +1,67 @@ +/* + * Copyright $year slavinson + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.kohsuke.github.extras; + +import org.kohsuke.github.HttpConnector; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; + +public class PreviewHttpConnector implements HttpConnector { + private final HttpConnector base; + private final int readTimeout, connectTimeout; + + /** + * @param connectTimeout HTTP connection timeout in milliseconds + * @param readTimeout HTTP read timeout in milliseconds + */ + public PreviewHttpConnector(HttpConnector base, int connectTimeout, int readTimeout) { + this.base = base; + this.connectTimeout = connectTimeout; + this.readTimeout = readTimeout; + } + + public PreviewHttpConnector(HttpConnector base, int timeout) { + this(base, timeout, timeout); + } + + public PreviewHttpConnector(HttpConnector base) { + this(base, ImpatientHttpConnector.CONNECT_TIMEOUT, ImpatientHttpConnector.READ_TIMEOUT); + } + + public PreviewHttpConnector() { + this(new HttpConnector() { + public HttpURLConnection connect(URL url) throws IOException { + return (HttpURLConnection) url.openConnection(); + } + }, ImpatientHttpConnector.CONNECT_TIMEOUT, ImpatientHttpConnector.READ_TIMEOUT); + } + + public HttpURLConnection connect(URL url) throws IOException { + HttpURLConnection con = base.connect(url); + con.setConnectTimeout(connectTimeout); + con.setReadTimeout(readTimeout); + con.addRequestProperty("Accept", PREVIEW_MEDIA_TYPE); + return con; + } + + /** + * Default connection timeout in milliseconds + */ + public static final String PREVIEW_MEDIA_TYPE = "application/vnd.github.drax-preview+json"; +} diff --git a/src/test/java/org/kohsuke/github/GHLicenseTest.java b/src/test/java/org/kohsuke/github/GHLicenseTest.java new file mode 100644 index 0000000000..e27f8057cd --- /dev/null +++ b/src/test/java/org/kohsuke/github/GHLicenseTest.java @@ -0,0 +1,220 @@ +/* + * The MIT License + * + * Copyright (c) 2016, Duncan Dickinson + * + * 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 org.apache.commons.io.IOUtils; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.kohsuke.github.extras.PreviewHttpConnector; + +import java.io.IOException; +import java.net.URL; +import java.util.List; + +/** + * @author Duncan Dickinson + */ +public class GHLicenseTest extends Assert { + private GitHub gitHub; + + @Before + public void setUp() throws Exception { + gitHub = new GitHubBuilder() + .fromCredentials() + .withConnector(new PreviewHttpConnector()) + .build(); + } + + /** + * Basic test to ensure that the list of licenses from {@link GitHub#listLicenses()} is returned + * + * @throws IOException + */ + @Test + public void listLicenses() throws IOException { + List licenses = gitHub.listLicenses(); + assertTrue(licenses.size() > 0); + } + + /** + * Tests that {@link GitHub#listLicenses()} returns the MIT license + * in the expected manner. + * + * @throws IOException + */ + @Test + public void listLicensesCheckIndividualLicense() throws IOException { + List licenses = gitHub.listLicenses(); + for (GHLicenseBase lic : licenses) { + if (lic.getKey().equals("mit")) { + assertTrue(lic.getUrl().equals(new URL("https://api.github.com/licenses/mit"))); + return; + } + } + fail("The MIT license was not found"); + } + + /** + * Checks that the request for an individual license using {@link GitHub#getLicense(String)} + * returns expected values (not all properties are checked) + * + * @throws IOException + */ + @Test + public void getLicense() throws IOException { + String key = "mit"; + GHLicense license = gitHub.getLicense(key); + assertNotNull(license); + assertTrue("The name is correct", license.getName().equals("MIT License")); + assertTrue("The HTML URL is correct", license.getHtmlUrl().equals(new URL("http://choosealicense.com/licenses/mit/"))); + } + + /** + * Attempts to list the licenses with a non-preview connection + * + * @throws IOException is expected to be thrown + */ + @Test(expected = IOException.class) + public void ListLicensesWithoutPreviewConnection() throws IOException { + GitHub.connect().listLicenses(); + } + + /** + * Accesses the 'kohsuke/github-api' repo using {@link GitHub#getRepository(String)} + * and checks that the license is correct + * + * @throws IOException + */ + @Test + public void checkRepositoryLicense() throws IOException { + GHRepository repo = gitHub.getRepository("kohsuke/github-api"); + GHLicenseBase license = repo.getLicense(); + assertNotNull("The license is populated", license); + assertTrue("The key is correct", license.getKey().equals("mit")); + assertTrue("The name is correct", license.getName().equals("MIT License")); + assertTrue("The URL is correct", license.getUrl().equals(new URL("https://api.github.com/licenses/mit"))); + } + + /** + * Accesses the 'atom/atom' repo using {@link GitHub#getRepository(String)} + * and checks that the license is correct + * + * @throws IOException + */ + @Test + public void checkRepositoryLicenseAtom() throws IOException { + GHRepository repo = gitHub.getRepository("atom/atom"); + GHLicenseBase license = repo.getLicense(); + assertNotNull("The license is populated", license); + assertTrue("The key is correct", license.getKey().equals("mit")); + assertTrue("The name is correct", license.getName().equals("MIT License")); + assertTrue("The URL is correct", license.getUrl().equals(new URL("https://api.github.com/licenses/mit"))); + } + + /** + * Accesses the 'pomes/pomes' repo using {@link GitHub#getRepository(String)} + * and checks that the license is correct + * + * @throws IOException + */ + @Test + public void checkRepositoryLicensePomes() throws IOException { + GHRepository repo = gitHub.getRepository("pomes/pomes"); + GHLicenseBase license = repo.getLicense(); + assertNotNull("The license is populated", license); + assertTrue("The key is correct", license.getKey().equals("apache-2.0")); + assertTrue("The name is correct", license.getName().equals("Apache License 2.0")); + assertTrue("The URL is correct", license.getUrl().equals(new URL("https://api.github.com/licenses/apache-2.0"))); + } + + /** + * Accesses the 'dedickinson/test-repo' repo using {@link GitHub#getRepository(String)} + * and checks that *no* license is returned as the repo doesn't have one + * + * @throws IOException + */ + @Test + public void checkRepositoryWithoutLicense() throws IOException { + GHRepository repo = gitHub.getRepository("dedickinson/test-repo"); + GHLicenseBase license = repo.getLicense(); + assertNull("There is no license", license); + } + + /** + * Accesses the 'kohsuke/github-api' repo using {@link GitHub#getRepository(String)} + * and then calls {@link GHRepository#getFullLicense()} and checks that certain + * properties are correct + * + * @throws IOException + */ + @Test + public void checkRepositoryFullLicense() throws IOException { + GHRepository repo = gitHub.getRepository("kohsuke/github-api"); + GHLicense license = repo.getFullLicense(); + assertNotNull("The license is populated", license); + assertTrue("The key is correct", license.getKey().equals("mit")); + assertTrue("The name is correct", license.getName().equals("MIT License")); + assertTrue("The URL is correct", license.getUrl().equals(new URL("https://api.github.com/licenses/mit"))); + assertTrue("The HTML URL is correct", license.getHtmlUrl().equals(new URL("http://choosealicense.com/licenses/mit/"))); + } + + /** + * Accesses the 'pomes/pomes' repo using {@link GitHub#getRepository(String)} + * and then calls {@link GHRepository#getLicenseContent()} and checks that certain + * properties are correct + * + * @throws IOException + */ + @Test + public void checkRepositoryLicenseContent() throws IOException { + GHRepository repo = gitHub.getRepository("pomes/pomes"); + GHContent content = repo.getLicenseContent(); + assertNotNull("The license content is populated", content); + assertTrue("The type is 'file'", content.getType().equals("file")); + assertTrue("The license file is 'LICENSE'", content.getName().equals("LICENSE")); + + if (content.getEncoding().equals("base64")) { + String licenseText = new String(IOUtils.toByteArray(content.read())); + assertTrue("The license appears to be an Apache License", licenseText.contains("Apache License")); + } else { + fail("Expected the license to be Base64 encoded but instead it was " + content.getEncoding()); + } + } + + /** + * Accesses the 'kohsuke/github-api' repo using {@link GitHub#getRepository(String)} + * but without using {@link PreviewHttpConnector} and ensures that the {@link GHRepository#getLicense()} + * call just returns null rather than raising an exception. This should indicate that + * non-preview connection requests aren't affected by the change in functionality + * + * @throws IOException + */ + @Test + public void checkRepositoryLicenseWithoutPreviewConnection() throws IOException { + GHRepository repo = GitHub.connect().getRepository("kohsuke/github-api"); + assertNull(repo.getLicense()); + } +} From 1de02a509948d2d0dea8a38b135a4bc83709217d Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 5 Aug 2016 20:19:36 -0700 Subject: [PATCH 152/390] Added a marker for preview APIs --- src/main/java/org/kohsuke/github/GHBranch.java | 3 +++ src/main/java/org/kohsuke/github/Preview.java | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 src/main/java/org/kohsuke/github/Preview.java diff --git a/src/main/java/org/kohsuke/github/GHBranch.java b/src/main/java/org/kohsuke/github/GHBranch.java index 1de47a156e..f4e90f6556 100644 --- a/src/main/java/org/kohsuke/github/GHBranch.java +++ b/src/main/java/org/kohsuke/github/GHBranch.java @@ -53,6 +53,7 @@ public String getSHA1() { /** * Disables branch protection and allows anyone with push access to push changes. */ + @Preview @Deprecated public void disableProtection() throws IOException { BranchProtection bp = new BranchProtection(); bp.enabled = false; @@ -64,6 +65,7 @@ public void disableProtection() throws IOException { * * @see GHCommitStatus#getContext() */ + @Preview @Deprecated public void enableProtection(EnforcementLevel level, Collection contexts) throws IOException { BranchProtection bp = new BranchProtection(); bp.enabled = true; @@ -73,6 +75,7 @@ public void enableProtection(EnforcementLevel level, Collection contexts setProtection(bp); } + @Preview @Deprecated public void enableProtection(EnforcementLevel level, String... contexts) throws IOException { enableProtection(level, Arrays.asList(contexts)); } diff --git a/src/main/java/org/kohsuke/github/Preview.java b/src/main/java/org/kohsuke/github/Preview.java new file mode 100644 index 0000000000..2eeed60456 --- /dev/null +++ b/src/main/java/org/kohsuke/github/Preview.java @@ -0,0 +1,18 @@ +package org.kohsuke.github; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Indicates that the method/class/etc marked maps to GitHub API in the preview period. + * + * These APIs are subject to change and not a part of the backward compatibility commitment. + * Always used in conjunction with 'deprecated' to raise awareness to clients. + * + * @author Kohsuke Kawaguchi + */ +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Preview { +} From 0cf4211aa54b74a489e49ca1b6c53b7c61c1b04b Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 5 Aug 2016 20:36:46 -0700 Subject: [PATCH 153/390] Merged GHLicense & GHLicenseBase Elsewhere in this library, whenever there are multiple forms of the same object, we map that to the same class and use lazy data retrieval to fill missing fields. --- .../kohsuke/github/GHContentWithLicense.java | 19 ++++ .../java/org/kohsuke/github/GHLicense.java | 103 ++++++++++++----- .../org/kohsuke/github/GHLicenseBase.java | 107 ------------------ .../java/org/kohsuke/github/GHObject.java | 2 +- .../java/org/kohsuke/github/GHRepository.java | 27 ++--- src/main/java/org/kohsuke/github/GitHub.java | 12 +- .../org/kohsuke/github/GHLicenseTest.java | 18 +-- 7 files changed, 123 insertions(+), 165 deletions(-) create mode 100644 src/main/java/org/kohsuke/github/GHContentWithLicense.java delete mode 100644 src/main/java/org/kohsuke/github/GHLicenseBase.java diff --git a/src/main/java/org/kohsuke/github/GHContentWithLicense.java b/src/main/java/org/kohsuke/github/GHContentWithLicense.java new file mode 100644 index 0000000000..a7dfa843d3 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHContentWithLicense.java @@ -0,0 +1,19 @@ +package org.kohsuke.github; + +/** + * {@link GHContent} with license information. + * + * @author Kohsuke Kawaguchi + * @see documentation + * @see GHRepository#getLicense() + */ +@Preview @Deprecated +class GHContentWithLicense extends GHContent { + GHLicense license; + + @Override + GHContentWithLicense wrap(GHRepository owner) { + super.wrap(owner); + return this; + } +} diff --git a/src/main/java/org/kohsuke/github/GHLicense.java b/src/main/java/org/kohsuke/github/GHLicense.java index baeb6c3d7d..24ca8bbbaa 100644 --- a/src/main/java/org/kohsuke/github/GHLicense.java +++ b/src/main/java/org/kohsuke/github/GHLicense.java @@ -24,8 +24,10 @@ 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.ArrayList; import java.util.List; @@ -33,17 +35,25 @@ /** * The GitHub Preview API's license information *

- * WARNING: This uses a PREVIEW API - you must use {@link org.kohsuke.github.extras.PreviewHttpConnector} + * WARNING: This uses a PREVIEW API - subject to change. * * @author Duncan Dickinson * @see GitHub#getLicense(String) - * @see GHRepository#getFullLicense() + * @see GHRepository#getLicense() * @see https://developer.github.com/v3/licenses/ */ +@Preview @Deprecated @SuppressWarnings({"UnusedDeclaration"}) @SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD"}, justification = "JSON API") -public class GHLicense extends GHLicenseBase { +public class GHLicense extends GHObject { + /*package almost final*/ GitHub root; + + // these fields are always present, even in the short form + protected String key, name; + + // the rest is only after populated + protected Boolean featured; protected String html_url, description, category, implementation, body; @@ -51,60 +61,101 @@ public class GHLicense extends GHLicenseBase { protected List permitted = new ArrayList(); protected List forbidden = new ArrayList(); - public URL getHtmlUrl() { + /** + * @return a mnemonic for the license + */ + public String getKey() { + return key; + } + + /** + * @return the license name + */ + public String getName() { + return name; + } + + /** + * @return API URL of this object. + */ + @WithBridgeMethods(value = String.class, adapterMethod = "urlToString") + public URL getUrl() { + return GitHub.parseURL(url); + } + + /** + * Featured licenses are bold in the new repository drop-down + * + * @return True if the license is featured, false otherwise + */ + public Boolean isFeatured() throws IOException { + populate(); + return featured; + } + + public URL getHtmlUrl() throws IOException { + populate(); return GitHub.parseURL(html_url); } - public String getDescription() { + public String getDescription() throws IOException { + populate(); return description; } - public String getCategory() { + public String getCategory() throws IOException { + populate(); return category; } - public String getImplementation() { + public String getImplementation() throws IOException { + populate(); return implementation; } - public List getRequired() { + public List getRequired() throws IOException { + populate(); return required; } - public List getPermitted() { + public List getPermitted() throws IOException { + populate(); return permitted; } - public List getForbidden() { + public List getForbidden() throws IOException { + populate(); return forbidden; } - public String getBody() { + public String getBody() throws IOException { + populate(); return body; } - @Override - public String toString() { - return "GHLicense{" + - "html_url='" + html_url + '\'' + - ", description='" + description + '\'' + - ", category='" + category + '\'' + - ", implementation='" + implementation + '\'' + - ", body='" + body + '\'' + - ", required=" + required + - ", permitted=" + permitted + - ", forbidden=" + forbidden + - ", htmlUrl=" + getHtmlUrl() + - "} " + super.toString(); + /** + * Fully populate the data by retrieving missing data. + * + * Depending on the original API call where this object is created, it may not contain everything. + */ + protected synchronized void populate() throws IOException { + if (description!=null) return; // already populated + + root.retrieve().to(url, this); } @Override public boolean equals(Object o) { - return super.equals(o); + if (this == o) return true; + if (!(o instanceof GHLicense)) return false; + + GHLicense that = (GHLicense) o; + return this.url.equals(that.url); } @Override public int hashCode() { - return super.hashCode(); + return url.hashCode(); } + } diff --git a/src/main/java/org/kohsuke/github/GHLicenseBase.java b/src/main/java/org/kohsuke/github/GHLicenseBase.java deleted file mode 100644 index e6c92359d8..0000000000 --- a/src/main/java/org/kohsuke/github/GHLicenseBase.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2016, Duncan Dickinson - * - * 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 com.infradna.tool.bridge_method_injector.WithBridgeMethods; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; - -import java.net.URL; - -/** - * The basic information for GitHub API licenses - as use in a number of - * API calls that only return the basic details - *

- * WARNING: This uses a PREVIEW API - you must use {@link org.kohsuke.github.extras.PreviewHttpConnector} - * - * @author Duncan Dickinson - * @see https://developer.github.com/v3/licenses/ - * @see GitHub#listLicenses() - * @see GHRepository#getLicense() - * @see GHLicense GHLicense subclass for the more comprehensive listing of properties - */ -@SuppressWarnings({"UnusedDeclaration"}) -@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", - "NP_UNWRITTEN_FIELD"}, justification = "JSON API") -public class GHLicenseBase { - - protected String key, name, url; - protected Boolean featured; - - /** - * @return a mnemonic for the license - */ - public String getKey() { - return key; - } - - /** - * @return the license name - */ - public String getName() { - return name; - } - - /** - * @return API URL of this object. - */ - @WithBridgeMethods(value = String.class, adapterMethod = "urlToString") - public URL getUrl() { - return GitHub.parseURL(url); - } - - /** - * Featured licenses are bold in the new repository drop-down - * - * @return True if the license is featured, false otherwise - */ - public Boolean isFeatured() { - return featured; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof GHLicenseBase)) return false; - - GHLicenseBase that = (GHLicenseBase) o; - - return getUrl().toString().equals(that.getUrl().toString()); - } - - @Override - public int hashCode() { - return getUrl().toString().hashCode(); - } - - @Override - public String toString() { - return "GHLicenseBase{" + - "key='" + key + '\'' + - ", name='" + name + '\'' + - ", url='" + url + '\'' + - ", featured=" + featured + - '}'; - } -} diff --git a/src/main/java/org/kohsuke/github/GHObject.java b/src/main/java/org/kohsuke/github/GHObject.java index 323e72cd29..a81d913a5c 100644 --- a/src/main/java/org/kohsuke/github/GHObject.java +++ b/src/main/java/org/kohsuke/github/GHObject.java @@ -51,7 +51,7 @@ public URL getUrl() { * URL of this object for humans, which renders some HTML. */ @WithBridgeMethods(value=String.class, adapterMethod="urlToString") - public abstract URL getHtmlUrl(); + public abstract URL getHtmlUrl() throws IOException; /** * When was this resource last updated? diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 0b7424311b..5430603363 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -70,10 +70,7 @@ public class GHRepository extends GHObject { * * See: https://developer.github.com/v3/licenses/ */ - /** - * The basic license details as returned from {@link GitHub#getRepository(String)} - */ - private GHLicenseBase license; + private GHLicense license; private String git_url, ssh_url, clone_url, svn_url, mirror_url; private GHUser owner; // not fully populated. beware. @@ -849,6 +846,8 @@ protected void wrapUp(GHCommitComment[] page) { } }; } + + /** * Gets the basic license details for the repository. *

* This is a preview item and requires you to use {@link org.kohsuke.github.extras.PreviewHttpConnector} @@ -858,20 +857,12 @@ protected void wrapUp(GHCommitComment[] page) { * * @throws IOException as usual but also if you don't use the preview connector */ - public GHLicenseBase getLicense() { - return license; - } - - /** - * Access the full license details - makes an additional API call - *

- * This is a preview item and requires you to use {@link org.kohsuke.github.extras.PreviewHttpConnector} - * - * @return the license details - * @throws IOException as usual but also if you don't use the preview connector - */ - public GHLicense getFullLicense() throws IOException { - return root.getLicense(license.getKey()); + @Preview @Deprecated + public GHLicense getLicense() throws IOException{ + return root.retrieve() + .withHeader("Accept","application/vnd.github.drax-preview+json") + .to(getApiTailUrl("license"), GHContentWithLicense.class) + .wrap(this).license; } /** diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index dd1e3593e3..a630e1f6d3 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -340,28 +340,32 @@ public GHRepository getRepository(String name) throws IOException { String[] tokens = name.split("/"); return retrieve().to("/repos/" + tokens[0] + '/' + tokens[1], GHRepository.class).wrap(this); } + /** * Returns a list of popular open source licenses * - * WARNING: This uses a PREVIEW API - you must use {@link org.kohsuke.github.extras.PreviewHttpConnector} + * WARNING: This uses a PREVIEW API. * * @see GitHub API - Licenses * * @return a list of popular open source licenses * @throws IOException if the HttpConnector doesn't pass in the preview header or other IO issue */ - public List listLicenses() throws IOException { - return Arrays.asList(retrieve().to("/licenses", GHLicenseBase[].class)); + @Preview @Deprecated + public List listLicenses() throws IOException { + return Arrays.asList(retrieve().to("/licenses", GHLicense[].class)); } /** * Returns the full details for a license * - * WARNING: This uses a PREVIEW API - you must use {@link org.kohsuke.github.extras.PreviewHttpConnector} + * WARNING: This uses a PREVIEW API. * * @param key The license key provided from the API * @return The license details * @throws IOException + * @see GHLicense#getKey() */ + @Preview @Deprecated public GHLicense getLicense(String key) throws IOException { return retrieve().to("/licenses/" + key, GHLicense.class); } diff --git a/src/test/java/org/kohsuke/github/GHLicenseTest.java b/src/test/java/org/kohsuke/github/GHLicenseTest.java index e27f8057cd..43a97b5ed9 100644 --- a/src/test/java/org/kohsuke/github/GHLicenseTest.java +++ b/src/test/java/org/kohsuke/github/GHLicenseTest.java @@ -55,7 +55,7 @@ public void setUp() throws Exception { */ @Test public void listLicenses() throws IOException { - List licenses = gitHub.listLicenses(); + List licenses = gitHub.listLicenses(); assertTrue(licenses.size() > 0); } @@ -67,8 +67,8 @@ public void listLicenses() throws IOException { */ @Test public void listLicensesCheckIndividualLicense() throws IOException { - List licenses = gitHub.listLicenses(); - for (GHLicenseBase lic : licenses) { + List licenses = gitHub.listLicenses(); + for (GHLicense lic : licenses) { if (lic.getKey().equals("mit")) { assertTrue(lic.getUrl().equals(new URL("https://api.github.com/licenses/mit"))); return; @@ -111,7 +111,7 @@ public void ListLicensesWithoutPreviewConnection() throws IOException { @Test public void checkRepositoryLicense() throws IOException { GHRepository repo = gitHub.getRepository("kohsuke/github-api"); - GHLicenseBase license = repo.getLicense(); + GHLicense license = repo.getLicense(); assertNotNull("The license is populated", license); assertTrue("The key is correct", license.getKey().equals("mit")); assertTrue("The name is correct", license.getName().equals("MIT License")); @@ -127,7 +127,7 @@ public void checkRepositoryLicense() throws IOException { @Test public void checkRepositoryLicenseAtom() throws IOException { GHRepository repo = gitHub.getRepository("atom/atom"); - GHLicenseBase license = repo.getLicense(); + GHLicense license = repo.getLicense(); assertNotNull("The license is populated", license); assertTrue("The key is correct", license.getKey().equals("mit")); assertTrue("The name is correct", license.getName().equals("MIT License")); @@ -143,7 +143,7 @@ public void checkRepositoryLicenseAtom() throws IOException { @Test public void checkRepositoryLicensePomes() throws IOException { GHRepository repo = gitHub.getRepository("pomes/pomes"); - GHLicenseBase license = repo.getLicense(); + GHLicense license = repo.getLicense(); assertNotNull("The license is populated", license); assertTrue("The key is correct", license.getKey().equals("apache-2.0")); assertTrue("The name is correct", license.getName().equals("Apache License 2.0")); @@ -159,13 +159,13 @@ public void checkRepositoryLicensePomes() throws IOException { @Test public void checkRepositoryWithoutLicense() throws IOException { GHRepository repo = gitHub.getRepository("dedickinson/test-repo"); - GHLicenseBase license = repo.getLicense(); + GHLicense license = repo.getLicense(); assertNull("There is no license", license); } /** * Accesses the 'kohsuke/github-api' repo using {@link GitHub#getRepository(String)} - * and then calls {@link GHRepository#getFullLicense()} and checks that certain + * and then calls {@link GHRepository#getLicense()} and checks that certain * properties are correct * * @throws IOException @@ -173,7 +173,7 @@ public void checkRepositoryWithoutLicense() throws IOException { @Test public void checkRepositoryFullLicense() throws IOException { GHRepository repo = gitHub.getRepository("kohsuke/github-api"); - GHLicense license = repo.getFullLicense(); + GHLicense license = repo.getLicense(); assertNotNull("The license is populated", license); assertTrue("The key is correct", license.getKey().equals("mit")); assertTrue("The name is correct", license.getName().equals("MIT License")); From 80aa75aab1af674d8e1662ec074c0fbc026ce290 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 5 Aug 2016 20:40:23 -0700 Subject: [PATCH 154/390] Added the wrap() method for a backpointer --- src/main/java/org/kohsuke/github/GHContentWithLicense.java | 2 ++ src/main/java/org/kohsuke/github/GHLicense.java | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHContentWithLicense.java b/src/main/java/org/kohsuke/github/GHContentWithLicense.java index a7dfa843d3..bbd115e649 100644 --- a/src/main/java/org/kohsuke/github/GHContentWithLicense.java +++ b/src/main/java/org/kohsuke/github/GHContentWithLicense.java @@ -14,6 +14,8 @@ class GHContentWithLicense extends GHContent { @Override GHContentWithLicense wrap(GHRepository owner) { super.wrap(owner); + if (license!=null) + license.wrap(owner.root); return this; } } diff --git a/src/main/java/org/kohsuke/github/GHLicense.java b/src/main/java/org/kohsuke/github/GHLicense.java index 24ca8bbbaa..b4dec87d32 100644 --- a/src/main/java/org/kohsuke/github/GHLicense.java +++ b/src/main/java/org/kohsuke/github/GHLicense.java @@ -158,4 +158,8 @@ public int hashCode() { return url.hashCode(); } + /*package*/ GHLicense wrap(GitHub root) { + this.root = root; + return this; + } } From 07b527a0f297e4ae909ba7c324e7d9c09df53e48 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 5 Aug 2016 20:40:34 -0700 Subject: [PATCH 155/390] Enumeration in GitHub should be PagedIterable --- src/main/java/org/kohsuke/github/GitHub.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index a630e1f6d3..8466ae6d54 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -348,11 +348,20 @@ public GHRepository getRepository(String name) throws IOException { * @see GitHub API - Licenses * * @return a list of popular open source licenses - * @throws IOException if the HttpConnector doesn't pass in the preview header or other IO issue */ @Preview @Deprecated - public List listLicenses() throws IOException { - return Arrays.asList(retrieve().to("/licenses", GHLicense[].class)); + public PagedIterable listLicenses() throws IOException { + return new PagedIterable() { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(retrieve().asIterator("/licenses", GHLicense[].class, pageSize)) { + @Override + protected void wrapUp(GHLicense[] page) { + for (GHLicense c : page) + c.wrap(GitHub.this); + } + }; + } + }; } /** From 70f0f5714a6bb1fa92ba6a52fa3692e87c02bea8 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 5 Aug 2016 20:44:10 -0700 Subject: [PATCH 156/390] While a use of custom HttpConnector is clever, it doesn't fit the current idiom of this library. --- .../github/extras/PreviewHttpConnector.java | 67 ------------------- .../org/kohsuke/github/GHLicenseTest.java | 15 ----- 2 files changed, 82 deletions(-) delete mode 100644 src/main/java/org/kohsuke/github/extras/PreviewHttpConnector.java diff --git a/src/main/java/org/kohsuke/github/extras/PreviewHttpConnector.java b/src/main/java/org/kohsuke/github/extras/PreviewHttpConnector.java deleted file mode 100644 index e1be7855f4..0000000000 --- a/src/main/java/org/kohsuke/github/extras/PreviewHttpConnector.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright $year slavinson - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.kohsuke.github.extras; - -import org.kohsuke.github.HttpConnector; - -import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.URL; - -public class PreviewHttpConnector implements HttpConnector { - private final HttpConnector base; - private final int readTimeout, connectTimeout; - - /** - * @param connectTimeout HTTP connection timeout in milliseconds - * @param readTimeout HTTP read timeout in milliseconds - */ - public PreviewHttpConnector(HttpConnector base, int connectTimeout, int readTimeout) { - this.base = base; - this.connectTimeout = connectTimeout; - this.readTimeout = readTimeout; - } - - public PreviewHttpConnector(HttpConnector base, int timeout) { - this(base, timeout, timeout); - } - - public PreviewHttpConnector(HttpConnector base) { - this(base, ImpatientHttpConnector.CONNECT_TIMEOUT, ImpatientHttpConnector.READ_TIMEOUT); - } - - public PreviewHttpConnector() { - this(new HttpConnector() { - public HttpURLConnection connect(URL url) throws IOException { - return (HttpURLConnection) url.openConnection(); - } - }, ImpatientHttpConnector.CONNECT_TIMEOUT, ImpatientHttpConnector.READ_TIMEOUT); - } - - public HttpURLConnection connect(URL url) throws IOException { - HttpURLConnection con = base.connect(url); - con.setConnectTimeout(connectTimeout); - con.setReadTimeout(readTimeout); - con.addRequestProperty("Accept", PREVIEW_MEDIA_TYPE); - return con; - } - - /** - * Default connection timeout in milliseconds - */ - public static final String PREVIEW_MEDIA_TYPE = "application/vnd.github.drax-preview+json"; -} diff --git a/src/test/java/org/kohsuke/github/GHLicenseTest.java b/src/test/java/org/kohsuke/github/GHLicenseTest.java index 43a97b5ed9..5335e1a9d3 100644 --- a/src/test/java/org/kohsuke/github/GHLicenseTest.java +++ b/src/test/java/org/kohsuke/github/GHLicenseTest.java @@ -44,7 +44,6 @@ public class GHLicenseTest extends Assert { public void setUp() throws Exception { gitHub = new GitHubBuilder() .fromCredentials() - .withConnector(new PreviewHttpConnector()) .build(); } @@ -203,18 +202,4 @@ public void checkRepositoryLicenseContent() throws IOException { fail("Expected the license to be Base64 encoded but instead it was " + content.getEncoding()); } } - - /** - * Accesses the 'kohsuke/github-api' repo using {@link GitHub#getRepository(String)} - * but without using {@link PreviewHttpConnector} and ensures that the {@link GHRepository#getLicense()} - * call just returns null rather than raising an exception. This should indicate that - * non-preview connection requests aren't affected by the change in functionality - * - * @throws IOException - */ - @Test - public void checkRepositoryLicenseWithoutPreviewConnection() throws IOException { - GHRepository repo = GitHub.connect().getRepository("kohsuke/github-api"); - assertNull(repo.getLicense()); - } } From 6a356c82a5129df674be98c2a73d5c1edf08b1bb Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 5 Aug 2016 20:44:45 -0700 Subject: [PATCH 157/390] Fixed up tests --- src/main/java/org/kohsuke/github/GHRepository.java | 8 +++----- src/test/java/org/kohsuke/github/GHLicenseTest.java | 8 +++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 5430603363..2ee35b4f74 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -850,10 +850,7 @@ protected void wrapUp(GHCommitComment[] page) { /** * Gets the basic license details for the repository. *

- * This is a preview item and requires you to use {@link org.kohsuke.github.extras.PreviewHttpConnector} - *

- * Warning: Only returns the basic license details. Use {@link GitHub#getLicense(String)} - * to get the full license information (hint: pass it {@link GHLicenseBase#getKey()}). + * This is a preview item and subject to change. * * @throws IOException as usual but also if you don't use the preview connector */ @@ -868,11 +865,12 @@ public GHLicense getLicense() throws IOException{ /** * Retrieves the contents of the repository's license file - makes an additional API call *

- * This is a preview item and requires you to use {@link org.kohsuke.github.extras.PreviewHttpConnector} + * This is a preview item and subject to change. * * @return details regarding the license contents * @throws IOException as usual but also if you don't use the preview connector */ + @Preview @Deprecated public GHContent getLicenseContent() throws IOException { return root.retrieve().to(getApiTailUrl("license"), GHContent.class).wrap(this); } diff --git a/src/test/java/org/kohsuke/github/GHLicenseTest.java b/src/test/java/org/kohsuke/github/GHLicenseTest.java index 5335e1a9d3..d32325f11d 100644 --- a/src/test/java/org/kohsuke/github/GHLicenseTest.java +++ b/src/test/java/org/kohsuke/github/GHLicenseTest.java @@ -28,11 +28,9 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.kohsuke.github.extras.PreviewHttpConnector; import java.io.IOException; import java.net.URL; -import java.util.List; /** * @author Duncan Dickinson @@ -54,8 +52,8 @@ public void setUp() throws Exception { */ @Test public void listLicenses() throws IOException { - List licenses = gitHub.listLicenses(); - assertTrue(licenses.size() > 0); + Iterable licenses = gitHub.listLicenses(); + assertTrue(licenses.iterator().hasNext()); } /** @@ -66,7 +64,7 @@ public void listLicenses() throws IOException { */ @Test public void listLicensesCheckIndividualLicense() throws IOException { - List licenses = gitHub.listLicenses(); + PagedIterable licenses = gitHub.listLicenses(); for (GHLicense lic : licenses) { if (lic.getKey().equals("mit")) { assertTrue(lic.getUrl().equals(new URL("https://api.github.com/licenses/mit"))); From 59324b008267ee9e3fdb3e5d7dc88a4c69bfd3e0 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 5 Aug 2016 20:47:08 -0700 Subject: [PATCH 158/390] Add preview media type header explicitly --- src/main/java/org/kohsuke/github/GHLicense.java | 4 +++- src/main/java/org/kohsuke/github/GHRepository.java | 14 +++++++++----- src/main/java/org/kohsuke/github/GitHub.java | 8 ++++++-- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHLicense.java b/src/main/java/org/kohsuke/github/GHLicense.java index b4dec87d32..283a60edff 100644 --- a/src/main/java/org/kohsuke/github/GHLicense.java +++ b/src/main/java/org/kohsuke/github/GHLicense.java @@ -141,7 +141,9 @@ public String getBody() throws IOException { protected synchronized void populate() throws IOException { if (description!=null) return; // already populated - root.retrieve().to(url, this); + root.retrieve() + .withHeader("Accept","application/vnd.github.drax-preview+json") + .to(url, this); } @Override diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 2ee35b4f74..a4a739f896 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -856,10 +856,7 @@ protected void wrapUp(GHCommitComment[] page) { */ @Preview @Deprecated public GHLicense getLicense() throws IOException{ - return root.retrieve() - .withHeader("Accept","application/vnd.github.drax-preview+json") - .to(getApiTailUrl("license"), GHContentWithLicense.class) - .wrap(this).license; + return getLicenseContent_().license; } /** @@ -872,7 +869,14 @@ public GHLicense getLicense() throws IOException{ */ @Preview @Deprecated public GHContent getLicenseContent() throws IOException { - return root.retrieve().to(getApiTailUrl("license"), GHContent.class).wrap(this); + return getLicenseContent_(); + } + + @Preview @Deprecated + private GHContentWithLicense getLicenseContent_() throws IOException { + return root.retrieve() + .withHeader("Accept","application/vnd.github.drax-preview+json") + .to(getApiTailUrl("license"), GHContentWithLicense.class).wrap(this); } /** diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 8466ae6d54..dff5f59148 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -353,7 +353,9 @@ public GHRepository getRepository(String name) throws IOException { public PagedIterable listLicenses() throws IOException { return new PagedIterable() { public PagedIterator _iterator(int pageSize) { - return new PagedIterator(retrieve().asIterator("/licenses", GHLicense[].class, pageSize)) { + return new PagedIterator(retrieve() + .withHeader("Accept","application/vnd.github.drax-preview+json") + .asIterator("/licenses", GHLicense[].class, pageSize)) { @Override protected void wrapUp(GHLicense[] page) { for (GHLicense c : page) @@ -376,7 +378,9 @@ protected void wrapUp(GHLicense[] page) { */ @Preview @Deprecated public GHLicense getLicense(String key) throws IOException { - return retrieve().to("/licenses/" + key, GHLicense.class); + return retrieve() + .withHeader("Accept","application/vnd.github.drax-preview+json") + .to("/licenses/" + key, GHLicense.class); } /** From cabbbf7f0203c4f22f8e0fd1baad488b623d83c8 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 5 Aug 2016 20:50:39 -0700 Subject: [PATCH 159/390] Handle 404 that represents "no license" --- .../java/org/kohsuke/github/GHRepository.java | 16 +++++++++++----- .../java/org/kohsuke/github/GHLicenseTest.java | 10 ---------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index a4a739f896..04e2b85101 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -853,10 +853,12 @@ protected void wrapUp(GHCommitComment[] page) { * This is a preview item and subject to change. * * @throws IOException as usual but also if you don't use the preview connector + * @return null if there's no license. */ @Preview @Deprecated public GHLicense getLicense() throws IOException{ - return getLicenseContent_().license; + GHContentWithLicense lic = getLicenseContent_(); + return lic!=null ? lic.license : null; } /** @@ -864,7 +866,7 @@ public GHLicense getLicense() throws IOException{ *

* This is a preview item and subject to change. * - * @return details regarding the license contents + * @return details regarding the license contents, or null if there's no license. * @throws IOException as usual but also if you don't use the preview connector */ @Preview @Deprecated @@ -874,9 +876,13 @@ public GHContent getLicenseContent() throws IOException { @Preview @Deprecated private GHContentWithLicense getLicenseContent_() throws IOException { - return root.retrieve() - .withHeader("Accept","application/vnd.github.drax-preview+json") - .to(getApiTailUrl("license"), GHContentWithLicense.class).wrap(this); + try { + return root.retrieve() + .withHeader("Accept","application/vnd.github.drax-preview+json") + .to(getApiTailUrl("license"), GHContentWithLicense.class).wrap(this); + } catch (FileNotFoundException e) { + return null; + } } /** diff --git a/src/test/java/org/kohsuke/github/GHLicenseTest.java b/src/test/java/org/kohsuke/github/GHLicenseTest.java index d32325f11d..b2cc73f928 100644 --- a/src/test/java/org/kohsuke/github/GHLicenseTest.java +++ b/src/test/java/org/kohsuke/github/GHLicenseTest.java @@ -89,16 +89,6 @@ public void getLicense() throws IOException { assertTrue("The HTML URL is correct", license.getHtmlUrl().equals(new URL("http://choosealicense.com/licenses/mit/"))); } - /** - * Attempts to list the licenses with a non-preview connection - * - * @throws IOException is expected to be thrown - */ - @Test(expected = IOException.class) - public void ListLicensesWithoutPreviewConnection() throws IOException { - GitHub.connect().listLicenses(); - } - /** * Accesses the 'kohsuke/github-api' repo using {@link GitHub#getRepository(String)} * and checks that the license is correct From a9fb4546e19e453766a46256c43232ed2ea35e6a Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 5 Aug 2016 20:56:11 -0700 Subject: [PATCH 160/390] Constants for preview media types --- src/main/java/org/kohsuke/github/GHBranch.java | 6 +++--- src/main/java/org/kohsuke/github/GHLicense.java | 6 +++--- src/main/java/org/kohsuke/github/GHRepository.java | 3 ++- src/main/java/org/kohsuke/github/GitHub.java | 9 +++------ src/main/java/org/kohsuke/github/Previews.java | 9 +++++++++ src/main/java/org/kohsuke/github/Requester.java | 4 ++++ 6 files changed, 24 insertions(+), 13 deletions(-) create mode 100644 src/main/java/org/kohsuke/github/Previews.java diff --git a/src/main/java/org/kohsuke/github/GHBranch.java b/src/main/java/org/kohsuke/github/GHBranch.java index f4e90f6556..4c80db9ef4 100644 --- a/src/main/java/org/kohsuke/github/GHBranch.java +++ b/src/main/java/org/kohsuke/github/GHBranch.java @@ -7,6 +7,8 @@ import java.util.Arrays; import java.util.Collection; +import static org.kohsuke.github.Previews.LOKI; + /** * A branch in a repository. * @@ -81,9 +83,7 @@ public void enableProtection(EnforcementLevel level, String... contexts) throws } private void setProtection(BranchProtection bp) throws IOException { - new Requester(root).method("PATCH") - .withHeader("Accept","application/vnd.github.loki-preview+json") - ._with("protection",bp).to(getApiRoute()); + new Requester(root).method("PATCH").withPreview(LOKI)._with("protection",bp).to(getApiRoute()); } String getApiRoute() { diff --git a/src/main/java/org/kohsuke/github/GHLicense.java b/src/main/java/org/kohsuke/github/GHLicense.java index 283a60edff..47bec0f71c 100644 --- a/src/main/java/org/kohsuke/github/GHLicense.java +++ b/src/main/java/org/kohsuke/github/GHLicense.java @@ -32,6 +32,8 @@ import java.util.ArrayList; import java.util.List; +import static org.kohsuke.github.Previews.DRAX; + /** * The GitHub Preview API's license information *

@@ -141,9 +143,7 @@ public String getBody() throws IOException { protected synchronized void populate() throws IOException { if (description!=null) return; // already populated - root.retrieve() - .withHeader("Accept","application/vnd.github.drax-preview+json") - .to(url, this); + root.retrieve().withPreview(DRAX).to(url, this); } @Override diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 04e2b85101..472adf41eb 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -51,6 +51,7 @@ import java.util.TreeMap; import static java.util.Arrays.asList; +import static org.kohsuke.github.Previews.DRAX; /** * A repository on GitHub. @@ -878,7 +879,7 @@ public GHContent getLicenseContent() throws IOException { private GHContentWithLicense getLicenseContent_() throws IOException { try { return root.retrieve() - .withHeader("Accept","application/vnd.github.drax-preview+json") + .withPreview(DRAX) .to(getApiTailUrl("license"), GHContentWithLicense.class).wrap(this); } catch (FileNotFoundException e) { return null; diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index dff5f59148..e5bf16b1de 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -27,6 +27,7 @@ import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE; import static java.util.logging.Level.FINE; import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; +import static org.kohsuke.github.Previews.DRAX; import java.io.ByteArrayInputStream; import java.io.FileNotFoundException; @@ -353,9 +354,7 @@ public GHRepository getRepository(String name) throws IOException { public PagedIterable listLicenses() throws IOException { return new PagedIterable() { public PagedIterator _iterator(int pageSize) { - return new PagedIterator(retrieve() - .withHeader("Accept","application/vnd.github.drax-preview+json") - .asIterator("/licenses", GHLicense[].class, pageSize)) { + return new PagedIterator(retrieve().withPreview(DRAX).asIterator("/licenses", GHLicense[].class, pageSize)) { @Override protected void wrapUp(GHLicense[] page) { for (GHLicense c : page) @@ -378,9 +377,7 @@ protected void wrapUp(GHLicense[] page) { */ @Preview @Deprecated public GHLicense getLicense(String key) throws IOException { - return retrieve() - .withHeader("Accept","application/vnd.github.drax-preview+json") - .to("/licenses/" + key, GHLicense.class); + return retrieve().withPreview(DRAX).to("/licenses/" + key, GHLicense.class); } /** diff --git a/src/main/java/org/kohsuke/github/Previews.java b/src/main/java/org/kohsuke/github/Previews.java new file mode 100644 index 0000000000..a5d061cbd4 --- /dev/null +++ b/src/main/java/org/kohsuke/github/Previews.java @@ -0,0 +1,9 @@ +package org.kohsuke.github; + +/** + * @author Kohsuke Kawaguchi + */ +/*package*/ class Previews { + static final String LOKI = "application/vnd.github.loki-preview+json"; + static final String DRAX = "application/vnd.github.drax-preview+json"; +} diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index 43c4e07694..ac492579ce 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -110,6 +110,10 @@ public Requester withHeader(String name, String value) { return this; } + /*package*/ Requester withPreview(String name) { + return withHeader("Accept",name); + } + /** * Makes a request with authentication credential. */ From 63f500ad7fff182662f35e3588f1cee4b3e72e2d Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 5 Aug 2016 21:11:00 -0700 Subject: [PATCH 161/390] Fixed issue #286 List commit API (https://developer.github.com/v3/repos/commits/#list-commits-on-a-repository) already populates short info, and so populate() call could be excessive. It's possible that the short info is always available and therefore there's never a need to call populate(), but that assumption is hard to test, so I'm leaving that in --- src/main/java/org/kohsuke/github/GHCommit.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHCommit.java b/src/main/java/org/kohsuke/github/GHCommit.java index 91510fc88c..6e606ef603 100644 --- a/src/main/java/org/kohsuke/github/GHCommit.java +++ b/src/main/java/org/kohsuke/github/GHCommit.java @@ -179,7 +179,8 @@ static class User { public ShortInfo getCommitShortInfo() throws IOException { - populate(); + if (commit==null) + populate(); return commit; } From 4f15b7c9fac50bfc280f7fad2aa11467aab63ca5 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 5 Aug 2016 21:19:32 -0700 Subject: [PATCH 162/390] NPE fix. type can be null --- src/main/java/org/kohsuke/github/Requester.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index ac492579ce..6175191ea6 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -516,7 +516,7 @@ private T parse(Class type, T instance) throws IOException { if (responseCode == 304) { return null; // special case handling for 304 unmodified, as the content will be "" } - if (responseCode == 204 && type.isArray()) { + if (responseCode == 204 && type!=null && type.isArray()) { // no content return type.cast(Array.newInstance(type.getComponentType(),0)); } From e2a1630cf4d555d9ecc3d07ec49f5315c2d24dc5 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 5 Aug 2016 21:28:54 -0700 Subject: [PATCH 163/390] findbug taming --- src/main/java/org/kohsuke/github/GHLicense.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/kohsuke/github/GHLicense.java b/src/main/java/org/kohsuke/github/GHLicense.java index 47bec0f71c..2c5c4299c1 100644 --- a/src/main/java/org/kohsuke/github/GHLicense.java +++ b/src/main/java/org/kohsuke/github/GHLicense.java @@ -49,6 +49,7 @@ @SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD"}, justification = "JSON API") public class GHLicense extends GHObject { + @SuppressFBWarnings("IS2_INCONSISTENT_SYNC") // root is set before the object is returned to the app /*package almost final*/ GitHub root; // these fields are always present, even in the short form From e9368fb04eaaa58ecaa6c3863140647b0a3f6f4f Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 5 Aug 2016 21:32:10 -0700 Subject: [PATCH 164/390] [maven-release-plugin] prepare release github-api-1.77 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index fa6bbacf9b..3a637f2227 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.77-SNAPSHOT + 1.77 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - HEAD + github-api-1.77 From df963cb71cd0495a255ad1dda74358c3cfb5b7e5 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 5 Aug 2016 21:32:15 -0700 Subject: [PATCH 165/390] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 3a637f2227..e24d8f1748 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.77 + 1.78-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - github-api-1.77 + HEAD From 38983df42dc43ba9b02917af1202ad87ef900e6e Mon Sep 17 00:00:00 2001 From: Jesse Glick Date: Mon, 19 Sep 2016 09:48:23 -0700 Subject: [PATCH 166/390] If we are a returning a collection of all things, we might as well use the maximum page size to minimize HTTP requests. --- src/main/java/org/kohsuke/github/GHOrganization.java | 2 +- src/main/java/org/kohsuke/github/GHPerson.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHOrganization.java b/src/main/java/org/kohsuke/github/GHOrganization.java index 0c62fd8a2a..f174decf2f 100644 --- a/src/main/java/org/kohsuke/github/GHOrganization.java +++ b/src/main/java/org/kohsuke/github/GHOrganization.java @@ -220,7 +220,7 @@ public GHTeam createTeam(String name, Permission p, GHRepository... repositories */ public List getRepositoriesWithOpenPullRequests() throws IOException { List r = new ArrayList(); - for (GHRepository repository : listRepositories()) { + for (GHRepository repository : listRepositories(100)) { repository.wrap(root); List pullRequests = repository.getPullRequests(GHIssueState.OPEN); if (pullRequests.size() > 0) { diff --git a/src/main/java/org/kohsuke/github/GHPerson.java b/src/main/java/org/kohsuke/github/GHPerson.java index ef93dd75aa..f8aae9a487 100644 --- a/src/main/java/org/kohsuke/github/GHPerson.java +++ b/src/main/java/org/kohsuke/github/GHPerson.java @@ -52,7 +52,7 @@ protected synchronized void populate() throws IOException { */ public synchronized Map getRepositories() throws IOException { Map repositories = new TreeMap(); - for (GHRepository r : listRepositories()) { + for (GHRepository r : listRepositories(100)) { repositories.put(r.getName(),r); } return Collections.unmodifiableMap(repositories); From 5334cb8688aa627c3ada1186902ec9e5ff342f92 Mon Sep 17 00:00:00 2001 From: Ben Sheats Date: Fri, 21 Oct 2016 11:40:01 -0400 Subject: [PATCH 167/390] url encode hashes in ref names --- src/main/java/org/kohsuke/github/GHRepository.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 472adf41eb..beba889f5f 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -765,6 +765,8 @@ public GHRef[] getRefs(String refType) throws IOException { * invalid ref type being requested */ public GHRef getRef(String refName) throws IOException { + // hashes in branch names must be replaced with the url encoded equivalent or this call will fail + refName = refName.replaceAll("#", "%23"); return root.retrieve().to(String.format("/repos/%s/%s/git/refs/%s", owner.login, name, refName), GHRef.class).wrap(root); } /** From 50b47fb73b538d4e7b80c9414c3410e727f0ace3 Mon Sep 17 00:00:00 2001 From: Stephen Connolly Date: Mon, 24 Oct 2016 21:12:56 +0100 Subject: [PATCH 168/390] Expose the commit dates --- .../java/org/kohsuke/github/GHCommit.java | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHCommit.java b/src/main/java/org/kohsuke/github/GHCommit.java index 6e606ef603..5872233567 100644 --- a/src/main/java/org/kohsuke/github/GHCommit.java +++ b/src/main/java/org/kohsuke/github/GHCommit.java @@ -2,12 +2,12 @@ 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.AbstractList; import java.util.ArrayList; import java.util.Collections; +import java.util.Date; import java.util.List; /** @@ -42,11 +42,19 @@ public GitUser getAuthor() { return author; } + public Date getAuthoredDate() { + return GitHub.parseDate(author.date); + } + @WithBridgeMethods(value = GHAuthor.class, castRequired = true) public GitUser getCommitter() { return committer; } + public Date getCommitDate() { + return GitHub.parseDate(author.date); + } + /** * Commit message. */ @@ -63,6 +71,7 @@ public int getCommentCount() { * @deprecated Use {@link GitUser} instead. */ public static class GHAuthor extends GitUser { + private String date; } public static class Stats { @@ -272,10 +281,29 @@ public GHUser getAuthor() throws IOException { return resolveUser(author); } + /** + * Gets the date the change was authored on. + * @return the date the change was authored on. + * @throws IOException if the information was not already fetched and an attempt at fetching the information failed. + */ + public Date getAuthoredDate() throws IOException { + return getCommitShortInfo().getAuthoredDate(); + } + public GHUser getCommitter() throws IOException { return resolveUser(committer); } + /** + * Gets the date the change was committed on. + * + * @return the date the change was committed on. + * @throws IOException if the information was not already fetched and an attempt at fetching the information failed. + */ + public Date getCommitDate() throws IOException { + return getCommitShortInfo().getCommitDate(); + } + private GHUser resolveUser(User author) throws IOException { if (author==null || author.login==null) return null; return owner.root.getUser(author.login); From b0df93bbcb5a27fa7268e2d778f708a66b100e69 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Mon, 24 Oct 2016 14:10:30 -0700 Subject: [PATCH 169/390] [maven-release-plugin] prepare release github-api-1.78 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index e24d8f1748..25340a1c27 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.78-SNAPSHOT + 1.78 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - HEAD + github-api-1.78 From 0d92d4ba618e49cfceda589650f01b5f5a7ca202 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Mon, 24 Oct 2016 14:10:35 -0700 Subject: [PATCH 170/390] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 25340a1c27..1f673f2768 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.78 + 1.79-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - github-api-1.78 + HEAD From 87fbb8ec987a68271adc0f43bd65593eeb91d2c1 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Mon, 24 Oct 2016 19:07:32 -0700 Subject: [PATCH 171/390] Copy/paste error --- src/main/java/org/kohsuke/github/GHCommit.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHCommit.java b/src/main/java/org/kohsuke/github/GHCommit.java index 5872233567..3740778480 100644 --- a/src/main/java/org/kohsuke/github/GHCommit.java +++ b/src/main/java/org/kohsuke/github/GHCommit.java @@ -52,7 +52,7 @@ public GitUser getCommitter() { } public Date getCommitDate() { - return GitHub.parseDate(author.date); + return GitHub.parseDate(committer.date); } /** From 4965fd5f4cdf90e1dc8ded82f214a3ddf2479c6d Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Mon, 24 Oct 2016 19:15:38 -0700 Subject: [PATCH 172/390] Noting possible TODO for the future --- src/main/java/org/kohsuke/github/GHRepository.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index beba889f5f..2a16feb2f2 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -766,6 +766,8 @@ public GHRef[] getRefs(String refType) throws IOException { */ public GHRef getRef(String refName) throws IOException { // hashes in branch names must be replaced with the url encoded equivalent or this call will fail + // FIXME: how about other URL unsafe characters, like space, @, : etc? do we need to be using URLEncoder.encode()? + // OTOH, '/' need no escaping refName = refName.replaceAll("#", "%23"); return root.retrieve().to(String.format("/repos/%s/%s/git/refs/%s", owner.login, name, refName), GHRef.class).wrap(root); } From 5d5c6cf71cd12517d4d3aff92506dc8131ea4035 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Mon, 24 Oct 2016 19:23:14 -0700 Subject: [PATCH 173/390] [maven-release-plugin] prepare release github-api-1.79 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 1f673f2768..9e3d54993c 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.79-SNAPSHOT + 1.79 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - HEAD + github-api-1.79 From fa3d0887efc52c36ca799923bad6c84601307843 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Mon, 24 Oct 2016 19:23:18 -0700 Subject: [PATCH 174/390] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 9e3d54993c..8d018c1a2f 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.79 + 1.80-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - github-api-1.79 + HEAD From 955e9899af32d1eaac4ceb57465005eb03589ac5 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Fri, 4 Nov 2016 00:09:59 +0800 Subject: [PATCH 175/390] Fix fields of GHRepository --- .../java/org/kohsuke/github/GHRepository.java | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 2a16feb2f2..f595bf632e 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -75,10 +75,10 @@ public class GHRepository extends GHObject { private String git_url, ssh_url, clone_url, svn_url, mirror_url; private GHUser owner; // not fully populated. beware. - private boolean has_issues, has_wiki, fork, has_downloads; + private boolean has_issues, has_wiki, fork, has_downloads, has_pages; @JsonProperty("private") private boolean _private; - private int watchers,forks,open_issues,size,network_count,subscribers_count; + private int forks_count, stargazers_count, watchers_count, size, open_issues_count, subscribers_count; private String pushed_at; private Map milestones = new HashMap(); @@ -358,8 +358,12 @@ public boolean isFork() { * 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; + public int getForksCount() { + return forks_count; + } + + public int getStargazersCount() { + return stargazers_count; } public boolean isPrivate() { @@ -370,16 +374,16 @@ public boolean hasDownloads() { return has_downloads; } - public int getWatchers() { - return watchers; + public boolean hasPages() { + return has_pages; } - public int getOpenIssueCount() { - return open_issues; + public int getWatchersCount() { + return watchers_count; } - public int getNetworkCount() { - return network_count; + public int getOpenIssueCount() { + return open_issues_count; } public int getSubscribersCount() { From 4daf6ba0579a081cf189a8e68d7c194f63a28596 Mon Sep 17 00:00:00 2001 From: Stephen Connolly Date: Tue, 8 Nov 2016 12:56:52 +0000 Subject: [PATCH 176/390] Add offline support to the API to make parsing events easier - When we receive events from a webhook, it is non-trivial to determine which GitHub instance the event came from or for that matter even if the event actually came from GitHub or GitHub Enterprise. - In order to ensure that the logic for parsing events does not get replicated in clients, we need to be able to call GitHub.parseEventPayload(Reader,Class) without knowing which GitHub the event originates from and without the resulting objects triggering API calls back to a GitHub - Thus we add GitHub.offline() to provide an off-line connection - Thus we modify some of the object classes to return best-effort objects when off-line - Add support for more of the event types into GHEventPayload - Add tests of the event payload and accessing critical fields when using GitHub.offline() --- .../org/kohsuke/github/GHCommitComment.java | 7 +- .../org/kohsuke/github/GHEventPayload.java | 373 +++++++++++++++ .../org/kohsuke/github/GHIssueComment.java | 4 +- .../java/org/kohsuke/github/GHPerson.java | 8 +- .../org/kohsuke/github/GHPullRequest.java | 4 +- .../java/org/kohsuke/github/GHRepository.java | 5 +- src/main/java/org/kohsuke/github/GitHub.java | 26 + .../org/kohsuke/github/HttpConnector.java | 9 + .../kohsuke/github/GHEventPayloadTest.java | 245 ++++++++++ .../java/org/kohsuke/github/GitHubTest.java | 14 + src/test/java/org/kohsuke/github/Payload.java | 12 + .../java/org/kohsuke/github/PayloadRule.java | 87 ++++ .../GHEventPayloadTest/commit_comment.json | 140 ++++++ .../github/GHEventPayloadTest/create.json | 113 +++++ .../github/GHEventPayloadTest/delete.json | 111 +++++ .../github/GHEventPayloadTest/deployment.json | 142 ++++++ .../GHEventPayloadTest/deployment_status.json | 172 +++++++ .../github/GHEventPayloadTest/fork.json | 196 ++++++++ .../github/GHEventPayloadTest/gollum.json | 118 +++++ .../GHEventPayloadTest/issue_comment.json | 182 +++++++ .../github/GHEventPayloadTest/issues.json | 156 ++++++ .../github/GHEventPayloadTest/label.json | 129 +++++ .../github/GHEventPayloadTest/member.json | 128 +++++ .../github/GHEventPayloadTest/membership.json | 61 +++ .../github/GHEventPayloadTest/milestone.json | 160 +++++++ .../github/GHEventPayloadTest/page_build.json | 139 ++++++ .../github/GHEventPayloadTest/public.json | 108 +++++ .../GHEventPayloadTest/pull_request.json | 412 ++++++++++++++++ .../pull_request_review.json | 440 +++++++++++++++++ .../pull_request_review_comment.json | 446 ++++++++++++++++++ .../github/GHEventPayloadTest/push.json | 174 +++++++ .../github/GHEventPayloadTest/release.json | 147 ++++++ .../github/GHEventPayloadTest/repository.json | 119 +++++ .../github/GHEventPayloadTest/status.json | 205 ++++++++ .../github/GHEventPayloadTest/team_add.json | 129 +++++ .../github/GHEventPayloadTest/watch.json | 109 +++++ 36 files changed, 5022 insertions(+), 8 deletions(-) create mode 100644 src/test/java/org/kohsuke/github/GHEventPayloadTest.java create mode 100644 src/test/java/org/kohsuke/github/Payload.java create mode 100644 src/test/java/org/kohsuke/github/PayloadRule.java create mode 100644 src/test/resources/org/kohsuke/github/GHEventPayloadTest/commit_comment.json create mode 100644 src/test/resources/org/kohsuke/github/GHEventPayloadTest/create.json create mode 100644 src/test/resources/org/kohsuke/github/GHEventPayloadTest/delete.json create mode 100644 src/test/resources/org/kohsuke/github/GHEventPayloadTest/deployment.json create mode 100644 src/test/resources/org/kohsuke/github/GHEventPayloadTest/deployment_status.json create mode 100644 src/test/resources/org/kohsuke/github/GHEventPayloadTest/fork.json create mode 100644 src/test/resources/org/kohsuke/github/GHEventPayloadTest/gollum.json create mode 100644 src/test/resources/org/kohsuke/github/GHEventPayloadTest/issue_comment.json create mode 100644 src/test/resources/org/kohsuke/github/GHEventPayloadTest/issues.json create mode 100644 src/test/resources/org/kohsuke/github/GHEventPayloadTest/label.json create mode 100644 src/test/resources/org/kohsuke/github/GHEventPayloadTest/member.json create mode 100644 src/test/resources/org/kohsuke/github/GHEventPayloadTest/membership.json create mode 100644 src/test/resources/org/kohsuke/github/GHEventPayloadTest/milestone.json create mode 100644 src/test/resources/org/kohsuke/github/GHEventPayloadTest/page_build.json create mode 100644 src/test/resources/org/kohsuke/github/GHEventPayloadTest/public.json create mode 100644 src/test/resources/org/kohsuke/github/GHEventPayloadTest/pull_request.json create mode 100644 src/test/resources/org/kohsuke/github/GHEventPayloadTest/pull_request_review.json create mode 100644 src/test/resources/org/kohsuke/github/GHEventPayloadTest/pull_request_review_comment.json create mode 100644 src/test/resources/org/kohsuke/github/GHEventPayloadTest/push.json create mode 100644 src/test/resources/org/kohsuke/github/GHEventPayloadTest/release.json create mode 100644 src/test/resources/org/kohsuke/github/GHEventPayloadTest/repository.json create mode 100644 src/test/resources/org/kohsuke/github/GHEventPayloadTest/status.json create mode 100644 src/test/resources/org/kohsuke/github/GHEventPayloadTest/team_add.json create mode 100644 src/test/resources/org/kohsuke/github/GHEventPayloadTest/watch.json diff --git a/src/main/java/org/kohsuke/github/GHCommitComment.java b/src/main/java/org/kohsuke/github/GHCommitComment.java index 7020f9b98f..64b658d2ff 100644 --- a/src/main/java/org/kohsuke/github/GHCommitComment.java +++ b/src/main/java/org/kohsuke/github/GHCommitComment.java @@ -21,7 +21,7 @@ public class GHCommitComment extends GHObject { String body, html_url, commit_id; Integer line; String path; - User user; + GHUser user; // not fully populated. beware. static class User { // TODO: what if someone who doesn't have an account on GitHub makes a commit? @@ -76,7 +76,7 @@ public int getLine() { * Gets the user who put this comment. */ public GHUser getUser() throws IOException { - return owner.root.getUser(user.login); + return owner == null || owner.root.isOffline() ? user : owner.root.getUser(user.login); } /** @@ -110,6 +110,9 @@ private String getApiTail() { GHCommitComment wrap(GHRepository owner) { this.owner = owner; + if (owner.root.isOffline()) { + user.wrapUp(owner.root); + } return this; } } diff --git a/src/main/java/org/kohsuke/github/GHEventPayload.java b/src/main/java/org/kohsuke/github/GHEventPayload.java index 08b112880d..7e54646485 100644 --- a/src/main/java/org/kohsuke/github/GHEventPayload.java +++ b/src/main/java/org/kohsuke/github/GHEventPayload.java @@ -1,5 +1,7 @@ package org.kohsuke.github; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSetter; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.io.Reader; import java.util.List; @@ -14,11 +16,28 @@ public abstract class GHEventPayload { protected GitHub root; + private GHUser sender; + /*package*/ GHEventPayload() { } + /** + * Gets the sender or {@code null} if accessed via the events API. + * @return the sender or {@code null} if accessed via the events API. + */ + public GHUser getSender() { + return sender; + } + + public void setSender(GHUser sender) { + this.sender = sender; + } + /*package*/ void wrapUp(GitHub root) { this.root = root; + if (sender != null) { + sender.wrapUp(root); + } } /** @@ -120,6 +139,290 @@ void wrapUp(GitHub root) { } } + /** + * A comment was added to a commit + * + * @see authoritative source + */ + @SuppressFBWarnings(value = {"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR", "NP_UNWRITTEN_FIELD" }, + justification = "Constructed by JSON deserialization") + public static class CommitComment extends GHEventPayload { + private String action; + private GHCommitComment comment; + private GHRepository repository; + + @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Comes from JSON deserialization") + public String getAction() { + return action; + } + + public GHCommitComment getComment() { + return comment; + } + + public void setComment(GHCommitComment comment) { + this.comment = comment; + } + + public GHRepository getRepository() { + return repository; + } + + public void setRepository(GHRepository repository) { + this.repository = repository; + } + + @Override + void wrapUp(GitHub root) { + super.wrapUp(root); + if (repository != null) { + repository.wrap(root); + comment.wrap(repository); + } + } + } + + /** + * A repository, branch, or tag was created + * + * @see authoritative source + */ + @SuppressFBWarnings(value = {"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR", "NP_UNWRITTEN_FIELD" }, + justification = "Constructed by JSON deserialization") + public static class Create extends GHEventPayload { + private String ref; + @JsonProperty("ref_type") + private String refType; + @JsonProperty("master_branch") + private String masterBranch; + private String description; + private GHRepository repository; + + @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Comes from JSON deserialization") + public String getRef() { + return ref; + } + + @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Comes from JSON deserialization") + public String getRefType() { + return refType; + } + + @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Comes from JSON deserialization") + public String getMasterBranch() { + return masterBranch; + } + + @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Comes from JSON deserialization") + public String getDescription() { + return description; + } + + public GHRepository getRepository() { + return repository; + } + + public void setRepository(GHRepository repository) { + this.repository = repository; + } + + @Override + void wrapUp(GitHub root) { + super.wrapUp(root); + if (repository != null) { + repository.wrap(root); + } + } + } + + /** + * A branch, or tag was deleted + * + * @see authoritative source + */ + @SuppressFBWarnings(value = {"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR", "NP_UNWRITTEN_FIELD" }, + justification = "Constructed by JSON deserialization") + public static class Delete extends GHEventPayload { + private String ref; + @JsonProperty("ref_type") + private String refType; + private GHRepository repository; + + @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Comes from JSON deserialization") + public String getRef() { + return ref; + } + + @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Comes from JSON deserialization") + public String getRefType() { + return refType; + } + + public GHRepository getRepository() { + return repository; + } + + public void setRepository(GHRepository repository) { + this.repository = repository; + } + + @Override + void wrapUp(GitHub root) { + super.wrapUp(root); + if (repository != null) { + repository.wrap(root); + } + } + } + + /** + * A deployment + * + * @see authoritative source + */ + @SuppressFBWarnings(value = {"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR", "NP_UNWRITTEN_FIELD" }, + justification = "Constructed by JSON deserialization") + public static class Deployment extends GHEventPayload { + private GHDeployment deployment; + private GHRepository repository; + + public GHDeployment getDeployment() { + return deployment; + } + + public void setDeployment(GHDeployment deployment) { + this.deployment = deployment; + } + + public GHRepository getRepository() { + return repository; + } + + public void setRepository(GHRepository repository) { + this.repository = repository; + } + + @Override + void wrapUp(GitHub root) { + super.wrapUp(root); + if (repository != null) { + repository.wrap(root); + deployment.wrap(repository); + } + } + } + + /** + * A deployment + * + * @see authoritative source + */ + @SuppressFBWarnings(value = {"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR", "NP_UNWRITTEN_FIELD" }, + justification = "Constructed by JSON deserialization") + public static class DeploymentStatus extends GHEventPayload { + @JsonProperty("deployment_status") + private GHDeploymentStatus deploymentStatus; + private GHDeployment deployment; + private GHRepository repository; + + public GHDeploymentStatus getDeploymentStatus() { + return deploymentStatus; + } + + public void setDeploymentStatus(GHDeploymentStatus deploymentStatus) { + this.deploymentStatus = deploymentStatus; + } + + public GHDeployment getDeployment() { + return deployment; + } + + public void setDeployment(GHDeployment deployment) { + this.deployment = deployment; + } + + public GHRepository getRepository() { + return repository; + } + + public void setRepository(GHRepository repository) { + this.repository = repository; + } + + @Override + void wrapUp(GitHub root) { + super.wrapUp(root); + if (repository != null) { + repository.wrap(root); + deployment.wrap(repository); + deploymentStatus.wrap(repository); + } + } + } + + /** + * A user forked a repository + * + * @see authoritative source + */ + @SuppressFBWarnings(value = {"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR", "NP_UNWRITTEN_FIELD" }, + justification = "Constructed by JSON deserialization") + public static class Fork extends GHEventPayload { + private GHRepository forkee; + private GHRepository repository; + + + public GHRepository getForkee() { + return forkee; + } + + public void setForkee(GHRepository forkee) { + this.forkee = forkee; + } + + public GHRepository getRepository() { + return repository; + } + + public void setRepository(GHRepository repository) { + this.repository = repository; + } + + @Override + void wrapUp(GitHub root) { + super.wrapUp(root); + forkee.wrap(root); + if (repository != null) { + repository.wrap(root); + } + } + } + + /** + * A repository was made public. + * + * @see authoritative source + */ + public static class Public extends GHEventPayload { + private GHRepository repository; + + public void setRepository(GHRepository repository) { + this.repository = repository; + } + + public GHRepository getRepository() { + return repository; + } + + @Override + void wrapUp(GitHub root) { + super.wrapUp(root); + if (repository!=null) + repository.wrap(root); + } + + } + /** * A commit was pushed. * @@ -127,6 +430,7 @@ void wrapUp(GitHub root) { */ public static class Push extends GHEventPayload { private String head, before; + private boolean created, deleted, forced; private String ref; private int size; private List commits; @@ -147,6 +451,11 @@ public String getBefore() { return before; } + @JsonSetter // alias + private void setAfter(String after) { + head = after; + } + /** * The full Git ref that was pushed. Example: “refs/heads/master” */ @@ -185,13 +494,19 @@ void wrapUp(GitHub root) { */ public static class PushCommit { private GitUser author; + private GitUser committer; private String url, sha, message; private boolean distinct; + private List added, removed, modified; public GitUser getAuthor() { return author; } + public GitUser getCommitter() { + return committer; + } + /** * Points to the commit API resource. */ @@ -203,6 +518,11 @@ public String getSha() { return sha; } + @JsonSetter + private void setId(String id) { + sha = id; + } + public String getMessage() { return message; } @@ -213,6 +533,59 @@ public String getMessage() { public boolean isDistinct() { return distinct; } + + public List getAdded() { + return added; + } + + public List getRemoved() { + return removed; + } + + public List getModified() { + return modified; + } + } + } + + /** + * A repository was created, deleted, made public, or made private. + * + * @see authoritative source + */ + public static class Repository extends GHEventPayload { + private String action; + private GHRepository repository; + private GHOrganization organization; + + public String getAction() { + return action; + } + + public void setRepository(GHRepository repository) { + this.repository = repository; + } + + public GHRepository getRepository() { + return repository; + } + + public GHOrganization getOrganization() { + return organization; + } + + public void setOrganization(GHOrganization organization) { + this.organization = organization; + } + + @Override + void wrapUp(GitHub root) { + super.wrapUp(root); + repository.wrap(root); + if (organization != null) { + organization.wrapUp(root); + } } + } } diff --git a/src/main/java/org/kohsuke/github/GHIssueComment.java b/src/main/java/org/kohsuke/github/GHIssueComment.java index 3179fa93a6..18d08bc7f4 100644 --- a/src/main/java/org/kohsuke/github/GHIssueComment.java +++ b/src/main/java/org/kohsuke/github/GHIssueComment.java @@ -35,7 +35,7 @@ public class GHIssueComment extends GHObject { GHIssue owner; private String body, gravatar_id; - private GHUser user; + private GHUser user; // not fully populated. beware. /*package*/ GHIssueComment wrapUp(GHIssue owner) { this.owner = owner; @@ -68,7 +68,7 @@ public String getUserName() { * Gets the user who posted this comment. */ public GHUser getUser() throws IOException { - return owner.root.getUser(user.getLogin()); + return owner == null || owner.root.isOffline() ? user : owner.root.getUser(user.getLogin()); } /** diff --git a/src/main/java/org/kohsuke/github/GHPerson.java b/src/main/java/org/kohsuke/github/GHPerson.java index f8aae9a487..67e157173f 100644 --- a/src/main/java/org/kohsuke/github/GHPerson.java +++ b/src/main/java/org/kohsuke/github/GHPerson.java @@ -38,8 +38,12 @@ public abstract class GHPerson extends GHObject { * Depending on the original API call where this object is created, it may not contain everything. */ protected synchronized void populate() throws IOException { - if (created_at!=null) return; // already populated - + if (created_at!=null) { + return; // already populated + } + if (root.isOffline()) { + return; // cannot populate, will have to live with what we have + } root.retrieve().to(url, this); } diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index dd3d93b758..a6becf495c 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -201,7 +201,9 @@ public String getMergeCommitSha() throws IOException { */ private void populate() throws IOException { if (merged_by!=null) return; // already populated - + if (root.isOffline()) { + return; // cannot populate, will have to live with what we have + } root.retrieve().to(url, this).wrapUp(owner); } diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 2a16feb2f2..a26d8e75a6 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -232,7 +232,7 @@ public String getLanguage() { } public GHUser getOwner() throws IOException { - return root.getUser(owner.login); // because 'owner' isn't fully populated + return root.isOffline() ? owner : root.getUser(owner.login); // because 'owner' isn't fully populated } public GHIssue getIssue(int id) throws IOException { @@ -1153,6 +1153,9 @@ public boolean remove(Object url) { /*package*/ GHRepository wrap(GitHub root) { this.root = root; + if (root.isOffline()) { + owner.wrapUp(root); + } return this; } diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index e5bf16b1de..04b3efefd3 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -215,6 +215,24 @@ public static GitHub connectToEnterpriseAnonymously(String apiUrl) throws IOExce return new GitHubBuilder().withEndpoint(apiUrl).build(); } + /** + * An off-line only {@link GitHub} useful for parsing event notification from an unknown source. + * + * All operations that require a connection will fail. + * + * @return An off-line only {@link GitHub}. + */ + public static GitHub offline() { + try { + return new GitHubBuilder() + .withEndpoint("https://api.github.invalid") + .withConnector(HttpConnector.OFFLINE) + .build(); + } catch (IOException e) { + throw new IllegalStateException("The offline implementation constructor should not connect", e); + } + } + /** * Is this an anonymous connection * @return {@code true} if operations that require authentication will fail. @@ -223,6 +241,14 @@ public boolean isAnonymous() { return login==null && encodedAuthorization==null; } + /** + * Is this an always offline "connection". + * @return {@code true} if this is an always offline "connection". + */ + public boolean isOffline() { + return connector == HttpConnector.OFFLINE; + } + public HttpConnector getConnector() { return connector; } diff --git a/src/main/java/org/kohsuke/github/HttpConnector.java b/src/main/java/org/kohsuke/github/HttpConnector.java index 5496268561..72f7ce5b05 100644 --- a/src/main/java/org/kohsuke/github/HttpConnector.java +++ b/src/main/java/org/kohsuke/github/HttpConnector.java @@ -29,4 +29,13 @@ public HttpURLConnection connect(URL url) throws IOException { return (HttpURLConnection) url.openConnection(); } }); + + /** + * Stub implementation that is always off-line. + */ + HttpConnector OFFLINE = new HttpConnector() { + public HttpURLConnection connect(URL url) throws IOException { + throw new IOException("Offline"); + } + }; } diff --git a/src/test/java/org/kohsuke/github/GHEventPayloadTest.java b/src/test/java/org/kohsuke/github/GHEventPayloadTest.java new file mode 100644 index 0000000000..f414b6e7b7 --- /dev/null +++ b/src/test/java/org/kohsuke/github/GHEventPayloadTest.java @@ -0,0 +1,245 @@ +package org.kohsuke.github; + +import org.junit.Rule; +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; + +public class GHEventPayloadTest { + + @Rule + public final PayloadRule payload = new PayloadRule(".json"); + + @Test + public void commit_comment() throws Exception { + GHEventPayload.CommitComment event = + GitHub.offline().parseEventPayload(payload.asReader(), GHEventPayload.CommitComment.class); + assertThat(event.getAction(), is("created")); + assertThat(event.getComment().getSHA1(), is("9049f1265b7d61be4a8904a9a27120d2064dab3b")); + assertThat(event.getComment().getUser().getLogin(), is("baxterthehacker")); + assertThat(event.getRepository().getName(), is("public-repo")); + assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); + assertThat(event.getSender().getLogin(), is("baxterthehacker")); + } + + @Test + public void create() throws Exception { + GHEventPayload.Create event = + GitHub.offline().parseEventPayload(payload.asReader(), GHEventPayload.Create.class); + assertThat(event.getRef(), is("0.0.1")); + assertThat(event.getRefType(), is("tag")); + assertThat(event.getMasterBranch(), is("master")); + assertThat(event.getDescription(), is("")); + assertThat(event.getRepository().getName(), is("public-repo")); + assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); + assertThat(event.getSender().getLogin(), is("baxterthehacker")); + } + + @Test + public void delete() throws Exception { + GHEventPayload.Delete event = + GitHub.offline().parseEventPayload(payload.asReader(), GHEventPayload.Delete.class); + assertThat(event.getRef(), is("simple-tag")); + assertThat(event.getRefType(), is("tag")); + assertThat(event.getRepository().getName(), is("public-repo")); + assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); + assertThat(event.getSender().getLogin(), is("baxterthehacker")); + } + + @Test + public void deployment() throws Exception { + GHEventPayload.Deployment event = + GitHub.offline().parseEventPayload(payload.asReader(), GHEventPayload.Deployment.class); + assertThat(event.getDeployment().getSha(), is("9049f1265b7d61be4a8904a9a27120d2064dab3b")); + assertThat(event.getDeployment().getEnvironment(), is("production")); + assertThat(event.getDeployment().getCreator().getLogin(), is("baxterthehacker")); + assertThat(event.getRepository().getName(), is("public-repo")); + assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); + assertThat(event.getSender().getLogin(), is("baxterthehacker")); + } + + @Test + public void deployment_status() throws Exception { + GHEventPayload.DeploymentStatus event = + GitHub.offline().parseEventPayload(payload.asReader(), GHEventPayload.DeploymentStatus.class); + assertThat(event.getDeploymentStatus().getState(), is(GHDeploymentState.SUCCESS)); + assertThat(event.getDeploymentStatus().getTargetUrl(), nullValue()); + assertThat(event.getDeployment().getSha(), is("9049f1265b7d61be4a8904a9a27120d2064dab3b")); + assertThat(event.getDeployment().getEnvironment(), is("production")); + assertThat(event.getDeployment().getCreator().getLogin(), is("baxterthehacker")); + assertThat(event.getRepository().getName(), is("public-repo")); + assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); + assertThat(event.getSender().getLogin(), is("baxterthehacker")); + } + + @Test + public void fork() throws Exception { + GHEventPayload.Fork event = + GitHub.offline().parseEventPayload(payload.asReader(), GHEventPayload.Fork.class); + assertThat(event.getForkee().getName(), is("public-repo")); + assertThat(event.getForkee().getOwner().getLogin(), is("baxterandthehackers")); + assertThat(event.getRepository().getName(), is("public-repo")); + assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); + assertThat(event.getSender().getLogin(), is("baxterandthehackers")); + } + +// TODO uncomment when we have GHPage implemented +// @Test +// public void gollum() throws Exception { +// GHEventPayload.Gollum event = +// GitHub.offline().parseEventPayload(payload.asReader(), GHEventPayload.Gollum.class); +// assertThat(event.getPages().size(), is(1)); +// GHPage page = event.getPages().get(0); +// assertThat(page.getName(), is("Home")); +// assertThat(page.getTitle(), is("Home")); +// assertThat(page.getSummary(), nullValue()); +// assertThat(page.getAction(), is("created")); +// assertThat(page.getSha(), is("91ea1bd42aa2ba166b86e8aefe049e9837214e67")); +// assertThat(page.getHtmlUrl(), is("https://github.com/baxterthehacker/public-repo/wiki/Home")); +// assertThat(event.getRepository().getName(), is("public-repo")); +// assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); +// assertThat(event.getSender().getLogin(), is("baxterthehacker")); +// } + + @Test + public void issue_comment() throws Exception { + GHEventPayload.IssueComment event = + GitHub.offline().parseEventPayload(payload.asReader(), GHEventPayload.IssueComment.class); + assertThat(event.getAction(), is("created")); + assertThat(event.getIssue().getNumber(), is(2)); + assertThat(event.getIssue().getTitle(), is("Spelling error in the README file")); + assertThat(event.getIssue().getState(), is(GHIssueState.OPEN)); + assertThat(event.getIssue().getLabels().size(), is(1)); + assertThat(event.getIssue().getLabels().iterator().next().getName(), is("bug")); + assertThat(event.getComment().getUser().getLogin(), is("baxterthehacker")); + assertThat(event.getComment().getBody(), is("You are totally right! I'll get this fixed right away.")); + assertThat(event.getRepository().getName(), is("public-repo")); + assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); + assertThat(event.getSender().getLogin(), is("baxterthehacker")); + } + +// TODO implement support classes and write test +// @Test +// public void issues() throws Exception {} + +// TODO implement support classes and write test +// @Test +// public void label() throws Exception {} + +// TODO implement support classes and write test +// @Test +// public void member() throws Exception {} + +// TODO implement support classes and write test +// @Test +// public void membership() throws Exception {} + +// TODO implement support classes and write test +// @Test +// public void milestone() throws Exception {} + +// TODO implement support classes and write test +// @Test +// public void page_build() throws Exception {} + + @Test + @Payload("public") + public void public_() throws Exception { + GHEventPayload.Public event = + GitHub.offline().parseEventPayload(payload.asReader(), GHEventPayload.Public.class); + assertThat(event.getRepository().getName(), is("public-repo")); + assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); + assertThat(event.getSender().getLogin(), is("baxterthehacker")); + } + + @Test + public void pull_request() throws Exception { + GHEventPayload.PullRequest event = + GitHub.offline().parseEventPayload(payload.asReader(), GHEventPayload.PullRequest.class); + assertThat(event.getAction(), is("opened")); + assertThat(event.getNumber(), is(1)); + assertThat(event.getPullRequest().getNumber(), is(1)); + assertThat(event.getPullRequest().getTitle(), is("Update the README with new information")); + assertThat(event.getPullRequest().getBody(), is("This is a pretty simple change that we need to pull into " + + "master.")); + assertThat(event.getPullRequest().getUser().getLogin(), is("baxterthehacker")); + assertThat(event.getPullRequest().getHead().getUser().getLogin(), is("baxterthehacker")); + assertThat(event.getPullRequest().getHead().getRef(), is("changes")); + assertThat(event.getPullRequest().getHead().getLabel(), is("baxterthehacker:changes")); + assertThat(event.getPullRequest().getHead().getSha(), is("0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c")); + assertThat(event.getPullRequest().getBase().getUser().getLogin(), is("baxterthehacker")); + assertThat(event.getPullRequest().getBase().getRef(), is("master")); + assertThat(event.getPullRequest().getBase().getLabel(), is("baxterthehacker:master")); + assertThat(event.getPullRequest().getBase().getSha(), is("9049f1265b7d61be4a8904a9a27120d2064dab3b")); + assertThat(event.getPullRequest().isMerged(), is(false)); + assertThat(event.getPullRequest().getMergeable(), nullValue()); + assertThat(event.getPullRequest().getMergeableState(), is("unknown")); + assertThat(event.getPullRequest().getMergedBy(), nullValue()); + assertThat(event.getPullRequest().getCommentsCount(), is(0)); + assertThat(event.getPullRequest().getReviewComments(), is(0)); + assertThat(event.getPullRequest().getAdditions(), is(1)); + assertThat(event.getPullRequest().getDeletions(), is(1)); + assertThat(event.getPullRequest().getChangedFiles(), is(1)); + assertThat(event.getRepository().getName(), is("public-repo")); + assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); + assertThat(event.getSender().getLogin(), is("baxterthehacker")); + } + +// TODO implement support classes and write test +// @Test +// public void pull_request_review() throws Exception {} + +// TODO implement support classes and write test +// @Test +// public void pull_request_review_comment() throws Exception {} + + @Test + public void push() throws Exception { + GHEventPayload.Push event = + GitHub.offline().parseEventPayload(payload.asReader(), GHEventPayload.Push.class); + assertThat(event.getRef(), is("refs/heads/changes")); + assertThat(event.getBefore(), is("9049f1265b7d61be4a8904a9a27120d2064dab3b")); + assertThat(event.getHead(), is("0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c")); + assertThat(event.getCommits().size(), is(1)); + assertThat(event.getCommits().get(0).getSha(), is("0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c")); + assertThat(event.getCommits().get(0).getAuthor().getEmail(), is("baxterthehacker@users.noreply.github.com")); + assertThat(event.getCommits().get(0).getCommitter().getEmail(), is("baxterthehacker@users.noreply.github.com")); + assertThat(event.getCommits().get(0).getAdded().size(), is(0)); + assertThat(event.getCommits().get(0).getRemoved().size(), is(0)); + assertThat(event.getCommits().get(0).getModified().size(), is(1)); + assertThat(event.getCommits().get(0).getModified().get(0), is("README.md")); + assertThat(event.getRepository().getName(), is("public-repo")); + assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); + assertThat(event.getSender().getLogin(), is("baxterthehacker")); + } + +// TODO implement support classes and write test +// @Test +// public void release() throws Exception {} + + @Test + public void repository() throws Exception { + GHEventPayload.Repository event = + GitHub.offline().parseEventPayload(payload.asReader(), GHEventPayload.Repository.class); + assertThat(event.getAction(), is("created")); + assertThat(event.getRepository().getName(), is("new-repository")); + assertThat(event.getRepository().getOwner().getLogin(), is("baxterandthehackers")); + assertThat(event.getOrganization().getLogin(), is("baxterandthehackers")); + assertThat(event.getSender().getLogin(), is("baxterthehacker")); + } + +// TODO implement support classes and write test +// @Test +// public void status() throws Exception {} + +// TODO implement support classes and write test +// @Test +// public void team_add() throws Exception {} + +// TODO implement support classes and write test +// @Test +// public void watch() throws Exception {} + +} diff --git a/src/test/java/org/kohsuke/github/GitHubTest.java b/src/test/java/org/kohsuke/github/GitHubTest.java index b8ae4ff0df..fe6faefac5 100644 --- a/src/test/java/org/kohsuke/github/GitHubTest.java +++ b/src/test/java/org/kohsuke/github/GitHubTest.java @@ -13,6 +13,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; @@ -20,6 +21,19 @@ * Unit test for {@link GitHub}. */ public class GitHubTest { + @Test + public void testOffline() throws Exception { + GitHub hub = GitHub.offline(); + assertEquals("https://api.github.invalid/test", hub.getApiURL("/test").toString()); + assertTrue(hub.isAnonymous()); + try { + hub.getRateLimit(); + fail("Offline instance should always fail"); + } catch (IOException e) { + assertEquals("Offline", e.getMessage()); + } + } + @Test public void testGitHubServerWithHttp() throws Exception { GitHub hub = GitHub.connectToEnterprise("http://enterprise.kohsuke.org/api/v3", "bogus","bogus"); diff --git a/src/test/java/org/kohsuke/github/Payload.java b/src/test/java/org/kohsuke/github/Payload.java new file mode 100644 index 0000000000..7365468d24 --- /dev/null +++ b/src/test/java/org/kohsuke/github/Payload.java @@ -0,0 +1,12 @@ +package org.kohsuke.github; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Payload { + String value(); +} diff --git a/src/test/java/org/kohsuke/github/PayloadRule.java b/src/test/java/org/kohsuke/github/PayloadRule.java new file mode 100644 index 0000000000..7f9364fdb2 --- /dev/null +++ b/src/test/java/org/kohsuke/github/PayloadRule.java @@ -0,0 +1,87 @@ +package org.kohsuke.github; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.nio.charset.Charset; +import org.apache.commons.io.IOUtils; +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +/** + * @author Stephen Connolly + */ +public class PayloadRule implements TestRule { + + private final String type; + + private Class testClass; + + private String resourceName; + + public PayloadRule(String type) { + this.type = type; + } + + public Statement apply(final Statement base, final Description description) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + Payload payload = description.getAnnotation(Payload.class); + resourceName = payload == null ? description.getMethodName() : payload.value(); + testClass = description.getTestClass(); + try { + base.evaluate(); + } finally { + resourceName = null; + } + } + }; + } + + public InputStream asInputStream() throws FileNotFoundException { + String name = resourceName.startsWith("/") + ? resourceName + type + : testClass.getSimpleName() + "/" + resourceName + type; + InputStream stream = testClass.getResourceAsStream(name); + if (stream == null) { + throw new FileNotFoundException(String.format("Resource %s from class %s", name, testClass)); + } + return stream; + } + + public byte[] asBytes() throws IOException { + InputStream input = asInputStream(); + try { + return IOUtils.toByteArray(input); + } finally { + IOUtils.closeQuietly(input); + } + } + + public String asString(Charset encoding) throws IOException { + return new String(asBytes(), encoding.name()); + } + + public String asString(String encoding) throws IOException { + return new String(asBytes(), encoding); + } + + public String asString() throws IOException { + return new String(asBytes(), Charset.defaultCharset().name()); + } + + public Reader asReader() throws FileNotFoundException { + return new InputStreamReader(asInputStream(), Charset.defaultCharset()); + } + + public Reader asReader(String encoding) throws IOException { + return new InputStreamReader(asInputStream(), encoding); + } + public Reader asReader(Charset encoding) throws FileNotFoundException { + return new InputStreamReader(asInputStream(), encoding); + } +} diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/commit_comment.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/commit_comment.json new file mode 100644 index 0000000000..bcf70894cd --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/commit_comment.json @@ -0,0 +1,140 @@ +{ + "action": "created", + "comment": { + "url": "https://api.github.com/repos/baxterthehacker/public-repo/comments/11056394", + "html_url": "https://github.com/baxterthehacker/public-repo/commit/9049f1265b7d61be4a8904a9a27120d2064dab3b#commitcomment-11056394", + "id": 11056394, + "user": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "position": null, + "line": null, + "path": null, + "commit_id": "9049f1265b7d61be4a8904a9a27120d2064dab3b", + "created_at": "2015-05-05T23:40:29Z", + "updated_at": "2015-05-05T23:40:29Z", + "body": "This is a really good change! :+1:" + }, + "repository": { + "id": 35129377, + "name": "public-repo", + "full_name": "baxterthehacker/public-repo", + "owner": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/baxterthehacker/public-repo", + "description": "", + "fork": false, + "url": "https://api.github.com/repos/baxterthehacker/public-repo", + "forks_url": "https://api.github.com/repos/baxterthehacker/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterthehacker/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterthehacker/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterthehacker/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterthehacker/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterthehacker/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterthehacker/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterthehacker/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterthehacker/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterthehacker/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterthehacker/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/baxterthehacker/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterthehacker/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterthehacker/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterthehacker/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterthehacker/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterthehacker/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterthehacker/public-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterthehacker/public-repo/releases{/id}", + "created_at": "2015-05-05T23:40:12Z", + "updated_at": "2015-05-05T23:40:12Z", + "pushed_at": "2015-05-05T23:40:27Z", + "git_url": "git://github.com/baxterthehacker/public-repo.git", + "ssh_url": "git@github.com:baxterthehacker/public-repo.git", + "clone_url": "https://github.com/baxterthehacker/public-repo.git", + "svn_url": "https://github.com/baxterthehacker/public-repo", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 2, + "forks": 0, + "open_issues": 2, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + } +} diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/create.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/create.json new file mode 100644 index 0000000000..51d690c378 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/create.json @@ -0,0 +1,113 @@ +{ + "ref": "0.0.1", + "ref_type": "tag", + "master_branch": "master", + "description": "", + "pusher_type": "user", + "repository": { + "id": 35129377, + "name": "public-repo", + "full_name": "baxterthehacker/public-repo", + "owner": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/baxterthehacker/public-repo", + "description": "", + "fork": false, + "url": "https://api.github.com/repos/baxterthehacker/public-repo", + "forks_url": "https://api.github.com/repos/baxterthehacker/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterthehacker/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterthehacker/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterthehacker/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterthehacker/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterthehacker/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterthehacker/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterthehacker/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterthehacker/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterthehacker/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterthehacker/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/baxterthehacker/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterthehacker/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterthehacker/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterthehacker/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterthehacker/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterthehacker/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterthehacker/public-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterthehacker/public-repo/releases{/id}", + "created_at": "2015-05-05T23:40:12Z", + "updated_at": "2015-05-05T23:40:30Z", + "pushed_at": "2015-05-05T23:40:38Z", + "git_url": "git://github.com/baxterthehacker/public-repo.git", + "ssh_url": "git@github.com:baxterthehacker/public-repo.git", + "clone_url": "https://github.com/baxterthehacker/public-repo.git", + "svn_url": "https://github.com/baxterthehacker/public-repo", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 2, + "forks": 0, + "open_issues": 2, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + } +} diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/delete.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/delete.json new file mode 100644 index 0000000000..0759bcd04a --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/delete.json @@ -0,0 +1,111 @@ +{ + "ref": "simple-tag", + "ref_type": "tag", + "pusher_type": "user", + "repository": { + "id": 35129377, + "name": "public-repo", + "full_name": "baxterthehacker/public-repo", + "owner": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/baxterthehacker/public-repo", + "description": "", + "fork": false, + "url": "https://api.github.com/repos/baxterthehacker/public-repo", + "forks_url": "https://api.github.com/repos/baxterthehacker/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterthehacker/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterthehacker/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterthehacker/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterthehacker/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterthehacker/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterthehacker/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterthehacker/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterthehacker/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterthehacker/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterthehacker/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/baxterthehacker/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterthehacker/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterthehacker/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterthehacker/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterthehacker/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterthehacker/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterthehacker/public-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterthehacker/public-repo/releases{/id}", + "created_at": "2015-05-05T23:40:12Z", + "updated_at": "2015-05-05T23:40:30Z", + "pushed_at": "2015-05-05T23:40:40Z", + "git_url": "git://github.com/baxterthehacker/public-repo.git", + "ssh_url": "git@github.com:baxterthehacker/public-repo.git", + "clone_url": "https://github.com/baxterthehacker/public-repo.git", + "svn_url": "https://github.com/baxterthehacker/public-repo", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 2, + "forks": 0, + "open_issues": 2, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + } +} diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/deployment.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/deployment.json new file mode 100644 index 0000000000..9f2ca9668f --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/deployment.json @@ -0,0 +1,142 @@ +{ + "deployment": { + "url": "https://api.github.com/repos/baxterthehacker/public-repo/deployments/710692", + "id": 710692, + "sha": "9049f1265b7d61be4a8904a9a27120d2064dab3b", + "ref": "master", + "task": "deploy", + "payload": { + }, + "environment": "production", + "description": null, + "creator": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "created_at": "2015-05-05T23:40:38Z", + "updated_at": "2015-05-05T23:40:38Z", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/deployments/710692/statuses", + "repository_url": "https://api.github.com/repos/baxterthehacker/public-repo" + }, + "repository": { + "id": 35129377, + "name": "public-repo", + "full_name": "baxterthehacker/public-repo", + "owner": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/baxterthehacker/public-repo", + "description": "", + "fork": false, + "url": "https://api.github.com/repos/baxterthehacker/public-repo", + "forks_url": "https://api.github.com/repos/baxterthehacker/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterthehacker/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterthehacker/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterthehacker/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterthehacker/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterthehacker/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterthehacker/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterthehacker/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterthehacker/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterthehacker/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterthehacker/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/baxterthehacker/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterthehacker/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterthehacker/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterthehacker/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterthehacker/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterthehacker/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterthehacker/public-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterthehacker/public-repo/releases{/id}", + "created_at": "2015-05-05T23:40:12Z", + "updated_at": "2015-05-05T23:40:30Z", + "pushed_at": "2015-05-05T23:40:38Z", + "git_url": "git://github.com/baxterthehacker/public-repo.git", + "ssh_url": "git@github.com:baxterthehacker/public-repo.git", + "clone_url": "https://github.com/baxterthehacker/public-repo.git", + "svn_url": "https://github.com/baxterthehacker/public-repo", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 2, + "forks": 0, + "open_issues": 2, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + } +} diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/deployment_status.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/deployment_status.json new file mode 100644 index 0000000000..e1dcd0706f --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/deployment_status.json @@ -0,0 +1,172 @@ +{ + "deployment_status": { + "url": "https://api.github.com/repos/baxterthehacker/public-repo/deployments/710692/statuses/1115122", + "id": 1115122, + "state": "success", + "creator": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "description": null, + "target_url": null, + "created_at": "2015-05-05T23:40:39Z", + "updated_at": "2015-05-05T23:40:39Z", + "deployment_url": "https://api.github.com/repos/baxterthehacker/public-repo/deployments/710692", + "repository_url": "https://api.github.com/repos/baxterthehacker/public-repo" + }, + "deployment": { + "url": "https://api.github.com/repos/baxterthehacker/public-repo/deployments/710692", + "id": 710692, + "sha": "9049f1265b7d61be4a8904a9a27120d2064dab3b", + "ref": "master", + "task": "deploy", + "payload": { + }, + "environment": "production", + "description": null, + "creator": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "created_at": "2015-05-05T23:40:38Z", + "updated_at": "2015-05-05T23:40:38Z", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/deployments/710692/statuses", + "repository_url": "https://api.github.com/repos/baxterthehacker/public-repo" + }, + "repository": { + "id": 35129377, + "name": "public-repo", + "full_name": "baxterthehacker/public-repo", + "owner": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/baxterthehacker/public-repo", + "description": "", + "fork": false, + "url": "https://api.github.com/repos/baxterthehacker/public-repo", + "forks_url": "https://api.github.com/repos/baxterthehacker/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterthehacker/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterthehacker/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterthehacker/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterthehacker/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterthehacker/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterthehacker/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterthehacker/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterthehacker/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterthehacker/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterthehacker/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/baxterthehacker/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterthehacker/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterthehacker/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterthehacker/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterthehacker/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterthehacker/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterthehacker/public-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterthehacker/public-repo/releases{/id}", + "created_at": "2015-05-05T23:40:12Z", + "updated_at": "2015-05-05T23:40:30Z", + "pushed_at": "2015-05-05T23:40:38Z", + "git_url": "git://github.com/baxterthehacker/public-repo.git", + "ssh_url": "git@github.com:baxterthehacker/public-repo.git", + "clone_url": "https://github.com/baxterthehacker/public-repo.git", + "svn_url": "https://github.com/baxterthehacker/public-repo", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 2, + "forks": 0, + "open_issues": 2, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + } +} diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/fork.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/fork.json new file mode 100644 index 0000000000..e01d3c50fc --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/fork.json @@ -0,0 +1,196 @@ +{ + "forkee": { + "id": 35129393, + "name": "public-repo", + "full_name": "baxterandthehackers/public-repo", + "owner": { + "login": "baxterandthehackers", + "id": 7649605, + "avatar_url": "https://avatars.githubusercontent.com/u/7649605?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterandthehackers", + "html_url": "https://github.com/baxterandthehackers", + "followers_url": "https://api.github.com/users/baxterandthehackers/followers", + "following_url": "https://api.github.com/users/baxterandthehackers/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterandthehackers/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterandthehackers/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterandthehackers/subscriptions", + "organizations_url": "https://api.github.com/users/baxterandthehackers/orgs", + "repos_url": "https://api.github.com/users/baxterandthehackers/repos", + "events_url": "https://api.github.com/users/baxterandthehackers/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterandthehackers/received_events", + "type": "Organization", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/baxterandthehackers/public-repo", + "description": "", + "fork": true, + "url": "https://api.github.com/repos/baxterandthehackers/public-repo", + "forks_url": "https://api.github.com/repos/baxterandthehackers/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterandthehackers/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterandthehackers/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterandthehackers/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterandthehackers/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterandthehackers/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterandthehackers/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterandthehackers/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterandthehackers/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterandthehackers/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterandthehackers/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterandthehackers/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterandthehackers/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterandthehackers/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterandthehackers/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterandthehackers/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterandthehackers/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterandthehackers/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterandthehackers/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterandthehackers/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterandthehackers/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterandthehackers/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterandthehackers/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterandthehackers/public-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/baxterandthehackers/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterandthehackers/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterandthehackers/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterandthehackers/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterandthehackers/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterandthehackers/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterandthehackers/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterandthehackers/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterandthehackers/public-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/baxterandthehackers/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterandthehackers/public-repo/releases{/id}", + "created_at": "2015-05-05T23:40:30Z", + "updated_at": "2015-05-05T23:40:30Z", + "pushed_at": "2015-05-05T23:40:27Z", + "git_url": "git://github.com/baxterandthehackers/public-repo.git", + "ssh_url": "git@github.com:baxterandthehackers/public-repo.git", + "clone_url": "https://github.com/baxterandthehackers/public-repo.git", + "svn_url": "https://github.com/baxterandthehackers/public-repo", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": false, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 0, + "forks": 0, + "open_issues": 0, + "watchers": 0, + "default_branch": "master", + "public": true + }, + "repository": { + "id": 35129377, + "name": "public-repo", + "full_name": "baxterthehacker/public-repo", + "owner": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/baxterthehacker/public-repo", + "description": "", + "fork": false, + "url": "https://api.github.com/repos/baxterthehacker/public-repo", + "forks_url": "https://api.github.com/repos/baxterthehacker/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterthehacker/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterthehacker/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterthehacker/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterthehacker/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterthehacker/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterthehacker/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterthehacker/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterthehacker/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterthehacker/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterthehacker/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/baxterthehacker/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterthehacker/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterthehacker/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterthehacker/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterthehacker/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterthehacker/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterthehacker/public-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterthehacker/public-repo/releases{/id}", + "created_at": "2015-05-05T23:40:12Z", + "updated_at": "2015-05-05T23:40:30Z", + "pushed_at": "2015-05-05T23:40:27Z", + "git_url": "git://github.com/baxterthehacker/public-repo.git", + "ssh_url": "git@github.com:baxterthehacker/public-repo.git", + "clone_url": "https://github.com/baxterthehacker/public-repo.git", + "svn_url": "https://github.com/baxterthehacker/public-repo", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 1, + "mirror_url": null, + "open_issues_count": 2, + "forks": 1, + "open_issues": 2, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "baxterandthehackers", + "id": 7649605, + "avatar_url": "https://avatars.githubusercontent.com/u/7649605?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterandthehackers", + "html_url": "https://github.com/baxterandthehackers", + "followers_url": "https://api.github.com/users/baxterandthehackers/followers", + "following_url": "https://api.github.com/users/baxterandthehackers/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterandthehackers/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterandthehackers/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterandthehackers/subscriptions", + "organizations_url": "https://api.github.com/users/baxterandthehackers/orgs", + "repos_url": "https://api.github.com/users/baxterandthehackers/repos", + "events_url": "https://api.github.com/users/baxterandthehackers/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterandthehackers/received_events", + "type": "Organization", + "site_admin": false + } +} diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/gollum.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/gollum.json new file mode 100644 index 0000000000..79527b91ca --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/gollum.json @@ -0,0 +1,118 @@ +{ + "pages": [ + { + "page_name": "Home", + "title": "Home", + "summary": null, + "action": "created", + "sha": "91ea1bd42aa2ba166b86e8aefe049e9837214e67", + "html_url": "https://github.com/baxterthehacker/public-repo/wiki/Home" + } + ], + "repository": { + "id": 35129377, + "name": "public-repo", + "full_name": "baxterthehacker/public-repo", + "owner": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/baxterthehacker/public-repo", + "description": "", + "fork": false, + "url": "https://api.github.com/repos/baxterthehacker/public-repo", + "forks_url": "https://api.github.com/repos/baxterthehacker/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterthehacker/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterthehacker/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterthehacker/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterthehacker/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterthehacker/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterthehacker/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterthehacker/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterthehacker/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterthehacker/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterthehacker/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/baxterthehacker/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterthehacker/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterthehacker/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterthehacker/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterthehacker/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterthehacker/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterthehacker/public-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterthehacker/public-repo/releases{/id}", + "created_at": "2015-05-05T23:40:12Z", + "updated_at": "2015-05-05T23:40:12Z", + "pushed_at": "2015-05-05T23:40:17Z", + "git_url": "git://github.com/baxterthehacker/public-repo.git", + "ssh_url": "git@github.com:baxterthehacker/public-repo.git", + "clone_url": "https://github.com/baxterthehacker/public-repo.git", + "svn_url": "https://github.com/baxterthehacker/public-repo", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 0, + "forks": 0, + "open_issues": 0, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "jasonrudolph", + "id": 2988, + "avatar_url": "https://avatars.githubusercontent.com/u/2988?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/jasonrudolph", + "html_url": "https://github.com/jasonrudolph", + "followers_url": "https://api.github.com/users/jasonrudolph/followers", + "following_url": "https://api.github.com/users/jasonrudolph/following{/other_user}", + "gists_url": "https://api.github.com/users/jasonrudolph/gists{/gist_id}", + "starred_url": "https://api.github.com/users/jasonrudolph/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/jasonrudolph/subscriptions", + "organizations_url": "https://api.github.com/users/jasonrudolph/orgs", + "repos_url": "https://api.github.com/users/jasonrudolph/repos", + "events_url": "https://api.github.com/users/jasonrudolph/events{/privacy}", + "received_events_url": "https://api.github.com/users/jasonrudolph/received_events", + "type": "User", + "site_admin": true + } +} diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/issue_comment.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/issue_comment.json new file mode 100644 index 0000000000..6f6e7d8975 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/issue_comment.json @@ -0,0 +1,182 @@ +{ + "action": "created", + "issue": { + "url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/2", + "labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/2/labels{/name}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/2/comments", + "events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/2/events", + "html_url": "https://github.com/baxterthehacker/public-repo/issues/2", + "id": 73464126, + "number": 2, + "title": "Spelling error in the README file", + "user": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "labels": [ + { + "url": "https://api.github.com/repos/baxterthehacker/public-repo/labels/bug", + "name": "bug", + "color": "fc2929" + } + ], + "state": "open", + "locked": false, + "assignee": null, + "milestone": null, + "comments": 1, + "created_at": "2015-05-05T23:40:28Z", + "updated_at": "2015-05-05T23:40:28Z", + "closed_at": null, + "body": "It looks like you accidently spelled 'commit' with two 't's." + }, + "comment": { + "url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/comments/99262140", + "html_url": "https://github.com/baxterthehacker/public-repo/issues/2#issuecomment-99262140", + "issue_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/2", + "id": 99262140, + "user": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "created_at": "2015-05-05T23:40:28Z", + "updated_at": "2015-05-05T23:40:28Z", + "body": "You are totally right! I'll get this fixed right away." + }, + "repository": { + "id": 35129377, + "name": "public-repo", + "full_name": "baxterthehacker/public-repo", + "owner": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/baxterthehacker/public-repo", + "description": "", + "fork": false, + "url": "https://api.github.com/repos/baxterthehacker/public-repo", + "forks_url": "https://api.github.com/repos/baxterthehacker/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterthehacker/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterthehacker/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterthehacker/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterthehacker/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterthehacker/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterthehacker/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterthehacker/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterthehacker/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterthehacker/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterthehacker/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/baxterthehacker/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterthehacker/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterthehacker/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterthehacker/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterthehacker/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterthehacker/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterthehacker/public-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterthehacker/public-repo/releases{/id}", + "created_at": "2015-05-05T23:40:12Z", + "updated_at": "2015-05-05T23:40:12Z", + "pushed_at": "2015-05-05T23:40:27Z", + "git_url": "git://github.com/baxterthehacker/public-repo.git", + "ssh_url": "git@github.com:baxterthehacker/public-repo.git", + "clone_url": "https://github.com/baxterthehacker/public-repo.git", + "svn_url": "https://github.com/baxterthehacker/public-repo", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 2, + "forks": 0, + "open_issues": 2, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + } +} diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/issues.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/issues.json new file mode 100644 index 0000000000..5e0c52b0c1 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/issues.json @@ -0,0 +1,156 @@ +{ + "action": "opened", + "issue": { + "url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/2", + "labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/2/labels{/name}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/2/comments", + "events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/2/events", + "html_url": "https://github.com/baxterthehacker/public-repo/issues/2", + "id": 73464126, + "number": 2, + "title": "Spelling error in the README file", + "user": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "labels": [ + { + "id": 208045946, + "url": "https://api.github.com/repos/baxterthehacker/public-repo/labels/bug", + "name": "bug", + "color": "fc2929", + "default": true + } + ], + "state": "open", + "locked": false, + "assignee": null, + "milestone": null, + "comments": 0, + "created_at": "2015-05-05T23:40:28Z", + "updated_at": "2015-05-05T23:40:28Z", + "closed_at": null, + "body": "It looks like you accidently spelled 'commit' with two 't's." + }, + "repository": { + "id": 35129377, + "name": "public-repo", + "full_name": "baxterthehacker/public-repo", + "owner": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/baxterthehacker/public-repo", + "description": "", + "fork": false, + "url": "https://api.github.com/repos/baxterthehacker/public-repo", + "forks_url": "https://api.github.com/repos/baxterthehacker/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterthehacker/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterthehacker/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterthehacker/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterthehacker/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterthehacker/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterthehacker/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterthehacker/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterthehacker/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterthehacker/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterthehacker/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/baxterthehacker/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterthehacker/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterthehacker/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterthehacker/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterthehacker/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterthehacker/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterthehacker/public-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterthehacker/public-repo/releases{/id}", + "created_at": "2015-05-05T23:40:12Z", + "updated_at": "2015-05-05T23:40:12Z", + "pushed_at": "2015-05-05T23:40:27Z", + "git_url": "git://github.com/baxterthehacker/public-repo.git", + "ssh_url": "git@github.com:baxterthehacker/public-repo.git", + "clone_url": "https://github.com/baxterthehacker/public-repo.git", + "svn_url": "https://github.com/baxterthehacker/public-repo", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 2, + "forks": 0, + "open_issues": 2, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + } +} diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/label.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/label.json new file mode 100644 index 0000000000..f85f636f89 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/label.json @@ -0,0 +1,129 @@ +{ + "action": "created", + "label": { + "url": "https://api.github.com/repos/baxterandthehackers/public-repo/labels/blocked", + "name": "blocked", + "color": "ff0000" + }, + "repository": { + "id": 67075329, + "name": "public-repo", + "full_name": "baxterandthehackers/public-repo", + "owner": { + "login": "baxterandthehackers", + "id": 4312013, + "avatar_url": "https://avatars.githubusercontent.com/u/4312013?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterandthehackers", + "html_url": "https://github.com/baxterandthehackers", + "followers_url": "https://api.github.com/users/baxterandthehackers/followers", + "following_url": "https://api.github.com/users/baxterandthehackers/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterandthehackers/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterandthehackers/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterandthehackers/subscriptions", + "organizations_url": "https://api.github.com/users/baxterandthehackers/orgs", + "repos_url": "https://api.github.com/users/baxterandthehackers/repos", + "events_url": "https://api.github.com/users/baxterandthehackers/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterandthehackers/received_events", + "type": "Organization", + "site_admin": false + }, + "private": true, + "html_url": "https://github.com/baxterandthehackers/public-repo", + "description": null, + "fork": false, + "url": "https://api.github.com/repos/baxterandthehackers/public-repo", + "forks_url": "https://api.github.com/repos/baxterandthehackers/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterandthehackers/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterandthehackers/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterandthehackers/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterandthehackers/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterandthehackers/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterandthehackers/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterandthehackers/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterandthehackers/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterandthehackers/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterandthehackers/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterandthehackers/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterandthehackers/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterandthehackers/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterandthehackers/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterandthehackers/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterandthehackers/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterandthehackers/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterandthehackers/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterandthehackers/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterandthehackers/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterandthehackers/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterandthehackers/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterandthehackers/public-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/baxterandthehackers/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterandthehackers/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterandthehackers/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterandthehackers/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterandthehackers/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterandthehackers/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterandthehackers/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterandthehackers/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterandthehackers/public-repo/notifications{?since,all, + participating}", + "labels_url": "https://api.github.com/repos/baxterandthehackers/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterandthehackers/public-repo/releases{/id}", + "deployments_url": "https://api.github.com/repos/baxterandthehackers/public-repo/deployments", + "created_at": "2016-08-31T21:38:51Z", + "updated_at": "2016-08-31T21:38:51Z", + "pushed_at": "2016-08-31T21:38:51Z", + "git_url": "git://github.com/baxterandthehackers/public-repo.git", + "ssh_url": "git@github.com:baxterandthehackers/public-repo.git", + "clone_url": "https://github.com/baxterandthehackers/public-repo.git", + "svn_url": "https://github.com/baxterandthehackers/public-repo", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 2, + "forks": 0, + "open_issues": 2, + "watchers": 0, + "default_branch": "master" + }, + "organization": { + "login": "baxterandthehackers", + "id": 4312013, + "url": "https://api.github.com/orgs/baxterandthehackers", + "repos_url": "https://api.github.com/orgs/baxterandthehackers/repos", + "events_url": "https://api.github.com/orgs/baxterandthehackers/events", + "hooks_url": "https://api.github.com/orgs/baxterandthehackers/hooks", + "issues_url": "https://api.github.com/orgs/baxterandthehackers/issues", + "members_url": "https://api.github.com/orgs/baxterandthehackers/members{/member}", + "public_members_url": "https://api.github.com/orgs/baxterandthehackers/public_members{/member}", + "avatar_url": "https://avatars.githubusercontent.com/u/4312013?v=3", + "description": "" + }, + "sender": { + "login": "baxterthehacker", + "id": 7649605, + "avatar_url": "https://avatars.githubusercontent.com/u/7649605?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": true + } +} diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/member.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/member.json new file mode 100644 index 0000000000..20305670e3 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/member.json @@ -0,0 +1,128 @@ +{ + "action": "added", + "member": { + "login": "octocat", + "id": 583231, + "avatar_url": "https://avatars.githubusercontent.com/u/583231?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "repository": { + "id": 35129377, + "name": "public-repo", + "full_name": "baxterthehacker/public-repo", + "owner": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/baxterthehacker/public-repo", + "description": "", + "fork": false, + "url": "https://api.github.com/repos/baxterthehacker/public-repo", + "forks_url": "https://api.github.com/repos/baxterthehacker/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterthehacker/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterthehacker/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterthehacker/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterthehacker/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterthehacker/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterthehacker/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterthehacker/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterthehacker/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterthehacker/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterthehacker/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/baxterthehacker/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterthehacker/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterthehacker/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterthehacker/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterthehacker/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterthehacker/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterthehacker/public-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterthehacker/public-repo/releases{/id}", + "created_at": "2015-05-05T23:40:12Z", + "updated_at": "2015-05-05T23:40:30Z", + "pushed_at": "2015-05-05T23:40:40Z", + "git_url": "git://github.com/baxterthehacker/public-repo.git", + "ssh_url": "git@github.com:baxterthehacker/public-repo.git", + "clone_url": "https://github.com/baxterthehacker/public-repo.git", + "svn_url": "https://github.com/baxterthehacker/public-repo", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 2, + "forks": 0, + "open_issues": 2, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + } +} diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/membership.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/membership.json new file mode 100644 index 0000000000..612d967f6d --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/membership.json @@ -0,0 +1,61 @@ +{ + "action": "added", + "scope": "team", + "member": { + "login": "kdaigle", + "id": 2501, + "avatar_url": "https://avatars.githubusercontent.com/u/2501?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/kdaigle", + "html_url": "https://github.com/kdaigle", + "followers_url": "https://api.github.com/users/kdaigle/followers", + "following_url": "https://api.github.com/users/kdaigle/following{/other_user}", + "gists_url": "https://api.github.com/users/kdaigle/gists{/gist_id}", + "starred_url": "https://api.github.com/users/kdaigle/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/kdaigle/subscriptions", + "organizations_url": "https://api.github.com/users/kdaigle/orgs", + "repos_url": "https://api.github.com/users/kdaigle/repos", + "events_url": "https://api.github.com/users/kdaigle/events{/privacy}", + "received_events_url": "https://api.github.com/users/kdaigle/received_events", + "type": "User", + "site_admin": true + }, + "sender": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=2", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "team": { + "name": "Contractors", + "id": 123456, + "slug": "contractors", + "permission": "admin", + "url": "https://api.github.com/teams/123456", + "members_url": "https://api.github.com/teams/123456/members{/member}", + "repositories_url": "https://api.github.com/teams/123456/repos" + }, + "organization": { + "login": "baxterandthehackers", + "id": 7649605, + "url": "https://api.github.com/orgs/baxterandthehackers", + "repos_url": "https://api.github.com/orgs/baxterandthehackers/repos", + "events_url": "https://api.github.com/orgs/baxterandthehackers/events", + "members_url": "https://api.github.com/orgs/baxterandthehackers/members{/member}", + "public_members_url": "https://api.github.com/orgs/baxterandthehackers/public_members{/member}", + "avatar_url": "https://avatars.githubusercontent.com/u/7649605?v=2" + } +} diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/milestone.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/milestone.json new file mode 100644 index 0000000000..7f262abd5c --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/milestone.json @@ -0,0 +1,160 @@ +{ + "action": "created", + "milestone": { + "url": "https://api.github.com/repos/baxterandthehackers/public-repo/milestones/3", + "html_url": "https://github.com/baxterandthehackers/public-repo/milestones/Test%20milestone%20creation%20webhook + %20from%20command%20line2", + "labels_url": "https://api.github.com/repos/baxterandthehackers/public-repo/milestones/3/labels", + "id": 2055681, + "number": 3, + "title": "I am a milestone", + "description": null, + "creator": { + "login": "baxterthehacker", + "id": 7649605, + "avatar_url": "https://avatars.githubusercontent.com/u/7649605?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": true + }, + "open_issues": 0, + "closed_issues": 0, + "state": "open", + "created_at": "2016-10-07T19:26:08Z", + "updated_at": "2016-10-07T19:26:08Z", + "due_on": null, + "closed_at": null + }, + "repository": { + "id": 70275481, + "name": "public-repo", + "full_name": "baxterandthehackers/public-repo", + "owner": { + "login": "baxterandthehackers", + "id": 4312013, + "avatar_url": "https://avatars.githubusercontent.com/u/4312013?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterandthehackers", + "html_url": "https://github.com/baxterandthehackers", + "followers_url": "https://api.github.com/users/baxterandthehackers/followers", + "following_url": "https://api.github.com/users/baxterandthehackers/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterandthehackers/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterandthehackers/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterandthehackers/subscriptions", + "organizations_url": "https://api.github.com/users/baxterandthehackers/orgs", + "repos_url": "https://api.github.com/users/baxterandthehackers/repos", + "events_url": "https://api.github.com/users/baxterandthehackers/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterandthehackers/received_events", + "type": "Organization", + "site_admin": false + }, + "private": true, + "html_url": "https://github.com/baxterandthehackers/public-repo", + "description": null, + "fork": false, + "url": "https://api.github.com/repos/baxterandthehackers/public-repo", + "forks_url": "https://api.github.com/repos/baxterandthehackers/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterandthehackers/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterandthehackers/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterandthehackers/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterandthehackers/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterandthehackers/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterandthehackers/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterandthehackers/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterandthehackers/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterandthehackers/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterandthehackers/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterandthehackers/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterandthehackers/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterandthehackers/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterandthehackers/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterandthehackers/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterandthehackers/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterandthehackers/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterandthehackers/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterandthehackers/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterandthehackers/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterandthehackers/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterandthehackers/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterandthehackers/public-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/baxterandthehackers/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterandthehackers/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterandthehackers/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterandthehackers/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterandthehackers/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterandthehackers/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterandthehackers/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterandthehackers/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterandthehackers/public-repo/notifications{?since,all, + participating}", + "labels_url": "https://api.github.com/repos/baxterandthehackers/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterandthehackers/public-repo/releases{/id}", + "deployments_url": "https://api.github.com/repos/baxterandthehackers/public-repo/deployments", + "created_at": "2016-10-07T19:10:12Z", + "updated_at": "2016-10-07T19:10:12Z", + "pushed_at": "2016-10-07T19:10:13Z", + "git_url": "git://github.com/baxterandthehackers/public-repo.git", + "ssh_url": "git@github.com:baxterandthehackers/public-repo.git", + "clone_url": "https://github.com/baxterandthehackers/public-repo.git", + "svn_url": "https://github.com/baxterandthehackers/public-repo", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 0, + "forks": 0, + "open_issues": 0, + "watchers": 0, + "default_branch": "master" + }, + "organization": { + "login": "baxterandthehackers", + "id": 4312013, + "url": "https://api.github.com/orgs/baxterandthehackers", + "repos_url": "https://api.github.com/orgs/baxterandthehackers/repos", + "events_url": "https://api.github.com/orgs/baxterandthehackers/events", + "hooks_url": "https://api.github.com/orgs/baxterandthehackers/hooks", + "issues_url": "https://api.github.com/orgs/baxterandthehackers/issues", + "members_url": "https://api.github.com/orgs/baxterandthehackers/members{/member}", + "public_members_url": "https://api.github.com/orgs/baxterandthehackers/public_members{/member}", + "avatar_url": "https://avatars.githubusercontent.com/u/4312013?v=3", + "description": "" + }, + "sender": { + "login": "baxterthehacker", + "id": 7649605, + "avatar_url": "https://avatars.githubusercontent.com/u/7649605?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": true + } +} diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/page_build.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/page_build.json new file mode 100644 index 0000000000..80962c016e --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/page_build.json @@ -0,0 +1,139 @@ +{ + "id": 15995382, + "build": { + "url": "https://api.github.com/repos/baxterthehacker/public-repo/pages/builds/15995382", + "status": "built", + "error": { + "message": null + }, + "pusher": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "commit": "053b99542c83021d6b202d1a1f5ecd5ef7084e55", + "duration": 3790, + "created_at": "2015-05-05T23:40:13Z", + "updated_at": "2015-05-05T23:40:17Z" + }, + "repository": { + "id": 35129377, + "name": "public-repo", + "full_name": "baxterthehacker/public-repo", + "owner": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/baxterthehacker/public-repo", + "description": "", + "fork": false, + "url": "https://api.github.com/repos/baxterthehacker/public-repo", + "forks_url": "https://api.github.com/repos/baxterthehacker/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterthehacker/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterthehacker/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterthehacker/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterthehacker/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterthehacker/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterthehacker/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterthehacker/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterthehacker/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterthehacker/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterthehacker/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/baxterthehacker/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterthehacker/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterthehacker/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterthehacker/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterthehacker/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterthehacker/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterthehacker/public-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterthehacker/public-repo/releases{/id}", + "created_at": "2015-05-05T23:40:12Z", + "updated_at": "2015-05-05T23:40:12Z", + "pushed_at": "2015-05-05T23:40:17Z", + "git_url": "git://github.com/baxterthehacker/public-repo.git", + "ssh_url": "git@github.com:baxterthehacker/public-repo.git", + "clone_url": "https://github.com/baxterthehacker/public-repo.git", + "svn_url": "https://github.com/baxterthehacker/public-repo", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 0, + "forks": 0, + "open_issues": 0, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + } +} diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/public.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/public.json new file mode 100644 index 0000000000..f596a54282 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/public.json @@ -0,0 +1,108 @@ +{ + "repository": { + "id": 35129377, + "name": "public-repo", + "full_name": "baxterthehacker/public-repo", + "owner": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/baxterthehacker/public-repo", + "description": "", + "fork": false, + "url": "https://api.github.com/repos/baxterthehacker/public-repo", + "forks_url": "https://api.github.com/repos/baxterthehacker/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterthehacker/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterthehacker/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterthehacker/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterthehacker/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterthehacker/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterthehacker/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterthehacker/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterthehacker/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterthehacker/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterthehacker/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/baxterthehacker/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterthehacker/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterthehacker/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterthehacker/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterthehacker/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterthehacker/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterthehacker/public-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterthehacker/public-repo/releases{/id}", + "created_at": "2015-05-05T23:40:12Z", + "updated_at": "2015-05-05T23:40:41Z", + "pushed_at": "2015-05-05T23:40:40Z", + "git_url": "git://github.com/baxterthehacker/public-repo.git", + "ssh_url": "git@github.com:baxterthehacker/public-repo.git", + "clone_url": "https://github.com/baxterthehacker/public-repo.git", + "svn_url": "https://github.com/baxterthehacker/public-repo", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 2, + "forks": 0, + "open_issues": 2, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + } +} diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/pull_request.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/pull_request.json new file mode 100644 index 0000000000..316cc4e8f7 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/pull_request.json @@ -0,0 +1,412 @@ +{ + "action": "opened", + "number": 1, + "pull_request": { + "url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/1", + "id": 34778301, + "html_url": "https://github.com/baxterthehacker/public-repo/pull/1", + "diff_url": "https://github.com/baxterthehacker/public-repo/pull/1.diff", + "patch_url": "https://github.com/baxterthehacker/public-repo/pull/1.patch", + "issue_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/1", + "number": 1, + "state": "open", + "locked": false, + "title": "Update the README with new information", + "user": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "body": "This is a pretty simple change that we need to pull into master.", + "created_at": "2015-05-05T23:40:27Z", + "updated_at": "2015-05-05T23:40:27Z", + "closed_at": null, + "merged_at": null, + "merge_commit_sha": null, + "assignee": null, + "milestone": null, + "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/1/commits", + "review_comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/1/comments", + "review_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/comments{/number}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/1/comments", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c", + "head": { + "label": "baxterthehacker:changes", + "ref": "changes", + "sha": "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c", + "user": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "repo": { + "id": 35129377, + "name": "public-repo", + "full_name": "baxterthehacker/public-repo", + "owner": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/baxterthehacker/public-repo", + "description": "", + "fork": false, + "url": "https://api.github.com/repos/baxterthehacker/public-repo", + "forks_url": "https://api.github.com/repos/baxterthehacker/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterthehacker/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterthehacker/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterthehacker/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterthehacker/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterthehacker/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterthehacker/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterthehacker/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterthehacker/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterthehacker/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterthehacker/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/baxterthehacker/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterthehacker/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterthehacker/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterthehacker/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterthehacker/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterthehacker/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterthehacker/public-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterthehacker/public-repo/releases{/id}", + "created_at": "2015-05-05T23:40:12Z", + "updated_at": "2015-05-05T23:40:12Z", + "pushed_at": "2015-05-05T23:40:26Z", + "git_url": "git://github.com/baxterthehacker/public-repo.git", + "ssh_url": "git@github.com:baxterthehacker/public-repo.git", + "clone_url": "https://github.com/baxterthehacker/public-repo.git", + "svn_url": "https://github.com/baxterthehacker/public-repo", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 1, + "forks": 0, + "open_issues": 1, + "watchers": 0, + "default_branch": "master" + } + }, + "base": { + "label": "baxterthehacker:master", + "ref": "master", + "sha": "9049f1265b7d61be4a8904a9a27120d2064dab3b", + "user": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "repo": { + "id": 35129377, + "name": "public-repo", + "full_name": "baxterthehacker/public-repo", + "owner": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/baxterthehacker/public-repo", + "description": "", + "fork": false, + "url": "https://api.github.com/repos/baxterthehacker/public-repo", + "forks_url": "https://api.github.com/repos/baxterthehacker/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterthehacker/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterthehacker/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterthehacker/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterthehacker/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterthehacker/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterthehacker/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterthehacker/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterthehacker/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterthehacker/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterthehacker/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/baxterthehacker/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterthehacker/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterthehacker/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterthehacker/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterthehacker/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterthehacker/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterthehacker/public-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterthehacker/public-repo/releases{/id}", + "created_at": "2015-05-05T23:40:12Z", + "updated_at": "2015-05-05T23:40:12Z", + "pushed_at": "2015-05-05T23:40:26Z", + "git_url": "git://github.com/baxterthehacker/public-repo.git", + "ssh_url": "git@github.com:baxterthehacker/public-repo.git", + "clone_url": "https://github.com/baxterthehacker/public-repo.git", + "svn_url": "https://github.com/baxterthehacker/public-repo", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 1, + "forks": 0, + "open_issues": 1, + "watchers": 0, + "default_branch": "master" + } + }, + "_links": { + "self": { + "href": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/1" + }, + "html": { + "href": "https://github.com/baxterthehacker/public-repo/pull/1" + }, + "issue": { + "href": "https://api.github.com/repos/baxterthehacker/public-repo/issues/1" + }, + "comments": { + "href": "https://api.github.com/repos/baxterthehacker/public-repo/issues/1/comments" + }, + "review_comments": { + "href": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/1/comments" + }, + "review_comment": { + "href": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/comments{/number}" + }, + "commits": { + "href": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/1/commits" + }, + "statuses": { + "href": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c" + } + }, + "merged": false, + "mergeable": null, + "mergeable_state": "unknown", + "merged_by": null, + "comments": 0, + "review_comments": 0, + "commits": 1, + "additions": 1, + "deletions": 1, + "changed_files": 1 + }, + "repository": { + "id": 35129377, + "name": "public-repo", + "full_name": "baxterthehacker/public-repo", + "owner": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/baxterthehacker/public-repo", + "description": "", + "fork": false, + "url": "https://api.github.com/repos/baxterthehacker/public-repo", + "forks_url": "https://api.github.com/repos/baxterthehacker/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterthehacker/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterthehacker/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterthehacker/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterthehacker/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterthehacker/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterthehacker/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterthehacker/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterthehacker/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterthehacker/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterthehacker/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/baxterthehacker/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterthehacker/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterthehacker/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterthehacker/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterthehacker/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterthehacker/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterthehacker/public-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterthehacker/public-repo/releases{/id}", + "created_at": "2015-05-05T23:40:12Z", + "updated_at": "2015-05-05T23:40:12Z", + "pushed_at": "2015-05-05T23:40:26Z", + "git_url": "git://github.com/baxterthehacker/public-repo.git", + "ssh_url": "git@github.com:baxterthehacker/public-repo.git", + "clone_url": "https://github.com/baxterthehacker/public-repo.git", + "svn_url": "https://github.com/baxterthehacker/public-repo", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 1, + "forks": 0, + "open_issues": 1, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + } +} diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/pull_request_review.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/pull_request_review.json new file mode 100644 index 0000000000..82c8396086 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/pull_request_review.json @@ -0,0 +1,440 @@ +{ + "action": "submitted", + "review": { + "id": 2626884, + "user": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "body": "Looks great!", + "submitted_at": "2016-10-03T23:39:09Z", + "state": "approved", + "html_url": "https://github.com/baxterthehacker/public-repo/pull/8#pullrequestreview-2626884", + "pull_request_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/8", + "_links": { + "html": { + "href": "https://github.com/baxterthehacker/public-repo/pull/8#pullrequestreview-2626884" + }, + "pull_request": { + "href": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/8" + } + } + }, + "pull_request": { + "url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/8", + "id": 87811438, + "html_url": "https://github.com/baxterthehacker/public-repo/pull/8", + "diff_url": "https://github.com/baxterthehacker/public-repo/pull/8.diff", + "patch_url": "https://github.com/baxterthehacker/public-repo/pull/8.patch", + "issue_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/8", + "number": 8, + "state": "open", + "locked": false, + "title": "Add a README description", + "user": { + "login": "skalnik", + "id": 2546, + "avatar_url": "https://avatars.githubusercontent.com/u/2546?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/skalnik", + "html_url": "https://github.com/skalnik", + "followers_url": "https://api.github.com/users/skalnik/followers", + "following_url": "https://api.github.com/users/skalnik/following{/other_user}", + "gists_url": "https://api.github.com/users/skalnik/gists{/gist_id}", + "starred_url": "https://api.github.com/users/skalnik/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/skalnik/subscriptions", + "organizations_url": "https://api.github.com/users/skalnik/orgs", + "repos_url": "https://api.github.com/users/skalnik/repos", + "events_url": "https://api.github.com/users/skalnik/events{/privacy}", + "received_events_url": "https://api.github.com/users/skalnik/received_events", + "type": "User", + "site_admin": true + }, + "body": "Just a few more details", + "created_at": "2016-10-03T23:37:43Z", + "updated_at": "2016-10-03T23:39:09Z", + "closed_at": null, + "merged_at": null, + "merge_commit_sha": "faea154a7decef6819754aab0f8c0e232e6c8b4f", + "assignee": null, + "assignees": [], + "milestone": null, + "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/8/commits", + "review_comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/8/comments", + "review_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/comments{/number}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/8/comments", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/b7a1f9c27caa4e03c14a88feb56e2d4f7500aa63", + "head": { + "label": "skalnik:patch-2", + "ref": "patch-2", + "sha": "b7a1f9c27caa4e03c14a88feb56e2d4f7500aa63", + "user": { + "login": "skalnik", + "id": 2546, + "avatar_url": "https://avatars.githubusercontent.com/u/2546?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/skalnik", + "html_url": "https://github.com/skalnik", + "followers_url": "https://api.github.com/users/skalnik/followers", + "following_url": "https://api.github.com/users/skalnik/following{/other_user}", + "gists_url": "https://api.github.com/users/skalnik/gists{/gist_id}", + "starred_url": "https://api.github.com/users/skalnik/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/skalnik/subscriptions", + "organizations_url": "https://api.github.com/users/skalnik/orgs", + "repos_url": "https://api.github.com/users/skalnik/repos", + "events_url": "https://api.github.com/users/skalnik/events{/privacy}", + "received_events_url": "https://api.github.com/users/skalnik/received_events", + "type": "User", + "site_admin": true + }, + "repo": { + "id": 69919152, + "name": "public-repo", + "full_name": "skalnik/public-repo", + "owner": { + "login": "skalnik", + "id": 2546, + "avatar_url": "https://avatars.githubusercontent.com/u/2546?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/skalnik", + "html_url": "https://github.com/skalnik", + "followers_url": "https://api.github.com/users/skalnik/followers", + "following_url": "https://api.github.com/users/skalnik/following{/other_user}", + "gists_url": "https://api.github.com/users/skalnik/gists{/gist_id}", + "starred_url": "https://api.github.com/users/skalnik/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/skalnik/subscriptions", + "organizations_url": "https://api.github.com/users/skalnik/orgs", + "repos_url": "https://api.github.com/users/skalnik/repos", + "events_url": "https://api.github.com/users/skalnik/events{/privacy}", + "received_events_url": "https://api.github.com/users/skalnik/received_events", + "type": "User", + "site_admin": true + }, + "private": false, + "html_url": "https://github.com/skalnik/public-repo", + "description": null, + "fork": true, + "url": "https://api.github.com/repos/skalnik/public-repo", + "forks_url": "https://api.github.com/repos/skalnik/public-repo/forks", + "keys_url": "https://api.github.com/repos/skalnik/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/skalnik/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/skalnik/public-repo/teams", + "hooks_url": "https://api.github.com/repos/skalnik/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/skalnik/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/skalnik/public-repo/events", + "assignees_url": "https://api.github.com/repos/skalnik/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/skalnik/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/skalnik/public-repo/tags", + "blobs_url": "https://api.github.com/repos/skalnik/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/skalnik/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/skalnik/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/skalnik/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/skalnik/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/skalnik/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/skalnik/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/skalnik/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/skalnik/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/skalnik/public-repo/subscription", + "commits_url": "https://api.github.com/repos/skalnik/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/skalnik/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/skalnik/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/skalnik/public-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/skalnik/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/skalnik/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/skalnik/public-repo/merges", + "archive_url": "https://api.github.com/repos/skalnik/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/skalnik/public-repo/downloads", + "issues_url": "https://api.github.com/repos/skalnik/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/skalnik/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/skalnik/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/skalnik/public-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/skalnik/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/skalnik/public-repo/releases{/id}", + "deployments_url": "https://api.github.com/repos/skalnik/public-repo/deployments", + "created_at": "2016-10-03T23:23:31Z", + "updated_at": "2016-08-15T17:19:01Z", + "pushed_at": "2016-10-03T23:36:52Z", + "git_url": "git://github.com/skalnik/public-repo.git", + "ssh_url": "git@github.com:skalnik/public-repo.git", + "clone_url": "https://github.com/skalnik/public-repo.git", + "svn_url": "https://github.com/skalnik/public-repo", + "homepage": null, + "size": 233, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": false, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 0, + "forks": 0, + "open_issues": 0, + "watchers": 0, + "default_branch": "master" + } + }, + "base": { + "label": "baxterthehacker:master", + "ref": "master", + "sha": "9049f1265b7d61be4a8904a9a27120d2064dab3b", + "user": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "repo": { + "id": 35129377, + "name": "public-repo", + "full_name": "baxterthehacker/public-repo", + "owner": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/baxterthehacker/public-repo", + "description": "", + "fork": false, + "url": "https://api.github.com/repos/baxterthehacker/public-repo", + "forks_url": "https://api.github.com/repos/baxterthehacker/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterthehacker/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterthehacker/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterthehacker/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterthehacker/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterthehacker/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterthehacker/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterthehacker/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterthehacker/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterthehacker/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterthehacker/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/baxterthehacker/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterthehacker/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterthehacker/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterthehacker/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterthehacker/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterthehacker/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterthehacker/public-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterthehacker/public-repo/releases{/id}", + "deployments_url": "https://api.github.com/repos/baxterthehacker/public-repo/deployments", + "created_at": "2015-05-05T23:40:12Z", + "updated_at": "2016-08-15T17:19:01Z", + "pushed_at": "2016-10-03T23:37:43Z", + "git_url": "git://github.com/baxterthehacker/public-repo.git", + "ssh_url": "git@github.com:baxterthehacker/public-repo.git", + "clone_url": "https://github.com/baxterthehacker/public-repo.git", + "svn_url": "https://github.com/baxterthehacker/public-repo", + "homepage": null, + "size": 233, + "stargazers_count": 2, + "watchers_count": 2, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 2, + "mirror_url": null, + "open_issues_count": 5, + "forks": 2, + "open_issues": 5, + "watchers": 2, + "default_branch": "master" + } + }, + "_links": { + "self": { + "href": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/8" + }, + "html": { + "href": "https://github.com/baxterthehacker/public-repo/pull/8" + }, + "issue": { + "href": "https://api.github.com/repos/baxterthehacker/public-repo/issues/8" + }, + "comments": { + "href": "https://api.github.com/repos/baxterthehacker/public-repo/issues/8/comments" + }, + "review_comments": { + "href": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/8/comments" + }, + "review_comment": { + "href": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/comments{/number}" + }, + "commits": { + "href": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/8/commits" + }, + "statuses": { + "href": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/b7a1f9c27caa4e03c14a88feb56e2d4f7500aa63" + } + } + }, + "repository": { + "id": 35129377, + "name": "public-repo", + "full_name": "baxterthehacker/public-repo", + "owner": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/baxterthehacker/public-repo", + "description": "", + "fork": false, + "url": "https://api.github.com/repos/baxterthehacker/public-repo", + "forks_url": "https://api.github.com/repos/baxterthehacker/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterthehacker/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterthehacker/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterthehacker/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterthehacker/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterthehacker/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterthehacker/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterthehacker/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterthehacker/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterthehacker/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterthehacker/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/baxterthehacker/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterthehacker/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterthehacker/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterthehacker/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterthehacker/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterthehacker/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterthehacker/public-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterthehacker/public-repo/releases{/id}", + "deployments_url": "https://api.github.com/repos/baxterthehacker/public-repo/deployments", + "created_at": "2015-05-05T23:40:12Z", + "updated_at": "2016-08-15T17:19:01Z", + "pushed_at": "2016-10-03T23:37:43Z", + "git_url": "git://github.com/baxterthehacker/public-repo.git", + "ssh_url": "git@github.com:baxterthehacker/public-repo.git", + "clone_url": "https://github.com/baxterthehacker/public-repo.git", + "svn_url": "https://github.com/baxterthehacker/public-repo", + "homepage": null, + "size": 233, + "stargazers_count": 2, + "watchers_count": 2, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 2, + "mirror_url": null, + "open_issues_count": 5, + "forks": 2, + "open_issues": 5, + "watchers": 2, + "default_branch": "master" + }, + "sender": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + } +} diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/pull_request_review_comment.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/pull_request_review_comment.json new file mode 100644 index 0000000000..a89b6b547d --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/pull_request_review_comment.json @@ -0,0 +1,446 @@ +{ + "action": "created", + "comment": { + "url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/comments/29724692", + "id": 29724692, + "diff_hunk": "@@ -1 +1 @@\n-# public-repo", + "path": "README.md", + "position": 1, + "original_position": 1, + "commit_id": "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c", + "original_commit_id": "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c", + "user": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "body": "Maybe you should use more emojji on this line.", + "created_at": "2015-05-05T23:40:27Z", + "updated_at": "2015-05-05T23:40:27Z", + "html_url": "https://github.com/baxterthehacker/public-repo/pull/1#discussion_r29724692", + "pull_request_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/1", + "_links": { + "self": { + "href": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/comments/29724692" + }, + "html": { + "href": "https://github.com/baxterthehacker/public-repo/pull/1#discussion_r29724692" + }, + "pull_request": { + "href": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/1" + } + } + }, + "pull_request": { + "url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/1", + "id": 34778301, + "html_url": "https://github.com/baxterthehacker/public-repo/pull/1", + "diff_url": "https://github.com/baxterthehacker/public-repo/pull/1.diff", + "patch_url": "https://github.com/baxterthehacker/public-repo/pull/1.patch", + "issue_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/1", + "number": 1, + "state": "open", + "locked": false, + "title": "Update the README with new information", + "user": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "body": "This is a pretty simple change that we need to pull into master.", + "created_at": "2015-05-05T23:40:27Z", + "updated_at": "2015-05-05T23:40:27Z", + "closed_at": null, + "merged_at": null, + "merge_commit_sha": "18721552ba489fb84e12958c1b5694b5475f7991", + "assignee": null, + "milestone": null, + "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/1/commits", + "review_comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/1/comments", + "review_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/comments{/number}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/1/comments", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c", + "head": { + "label": "baxterthehacker:changes", + "ref": "changes", + "sha": "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c", + "user": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "repo": { + "id": 35129377, + "name": "public-repo", + "full_name": "baxterthehacker/public-repo", + "owner": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/baxterthehacker/public-repo", + "description": "", + "fork": false, + "url": "https://api.github.com/repos/baxterthehacker/public-repo", + "forks_url": "https://api.github.com/repos/baxterthehacker/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterthehacker/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterthehacker/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterthehacker/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterthehacker/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterthehacker/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterthehacker/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterthehacker/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterthehacker/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterthehacker/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterthehacker/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/baxterthehacker/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterthehacker/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterthehacker/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterthehacker/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterthehacker/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterthehacker/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterthehacker/public-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterthehacker/public-repo/releases{/id}", + "created_at": "2015-05-05T23:40:12Z", + "updated_at": "2015-05-05T23:40:12Z", + "pushed_at": "2015-05-05T23:40:27Z", + "git_url": "git://github.com/baxterthehacker/public-repo.git", + "ssh_url": "git@github.com:baxterthehacker/public-repo.git", + "clone_url": "https://github.com/baxterthehacker/public-repo.git", + "svn_url": "https://github.com/baxterthehacker/public-repo", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 1, + "forks": 0, + "open_issues": 1, + "watchers": 0, + "default_branch": "master" + } + }, + "base": { + "label": "baxterthehacker:master", + "ref": "master", + "sha": "9049f1265b7d61be4a8904a9a27120d2064dab3b", + "user": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "repo": { + "id": 35129377, + "name": "public-repo", + "full_name": "baxterthehacker/public-repo", + "owner": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/baxterthehacker/public-repo", + "description": "", + "fork": false, + "url": "https://api.github.com/repos/baxterthehacker/public-repo", + "forks_url": "https://api.github.com/repos/baxterthehacker/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterthehacker/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterthehacker/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterthehacker/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterthehacker/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterthehacker/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterthehacker/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterthehacker/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterthehacker/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterthehacker/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterthehacker/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/baxterthehacker/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterthehacker/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterthehacker/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterthehacker/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterthehacker/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterthehacker/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterthehacker/public-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterthehacker/public-repo/releases{/id}", + "created_at": "2015-05-05T23:40:12Z", + "updated_at": "2015-05-05T23:40:12Z", + "pushed_at": "2015-05-05T23:40:27Z", + "git_url": "git://github.com/baxterthehacker/public-repo.git", + "ssh_url": "git@github.com:baxterthehacker/public-repo.git", + "clone_url": "https://github.com/baxterthehacker/public-repo.git", + "svn_url": "https://github.com/baxterthehacker/public-repo", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 1, + "forks": 0, + "open_issues": 1, + "watchers": 0, + "default_branch": "master" + } + }, + "_links": { + "self": { + "href": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/1" + }, + "html": { + "href": "https://github.com/baxterthehacker/public-repo/pull/1" + }, + "issue": { + "href": "https://api.github.com/repos/baxterthehacker/public-repo/issues/1" + }, + "comments": { + "href": "https://api.github.com/repos/baxterthehacker/public-repo/issues/1/comments" + }, + "review_comments": { + "href": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/1/comments" + }, + "review_comment": { + "href": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/comments{/number}" + }, + "commits": { + "href": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/1/commits" + }, + "statuses": { + "href": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c" + } + } + }, + "repository": { + "id": 35129377, + "name": "public-repo", + "full_name": "baxterthehacker/public-repo", + "owner": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/baxterthehacker/public-repo", + "description": "", + "fork": false, + "url": "https://api.github.com/repos/baxterthehacker/public-repo", + "forks_url": "https://api.github.com/repos/baxterthehacker/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterthehacker/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterthehacker/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterthehacker/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterthehacker/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterthehacker/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterthehacker/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterthehacker/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterthehacker/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterthehacker/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterthehacker/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/baxterthehacker/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterthehacker/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterthehacker/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterthehacker/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterthehacker/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterthehacker/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterthehacker/public-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterthehacker/public-repo/releases{/id}", + "created_at": "2015-05-05T23:40:12Z", + "updated_at": "2015-05-05T23:40:12Z", + "pushed_at": "2015-05-05T23:40:27Z", + "git_url": "git://github.com/baxterthehacker/public-repo.git", + "ssh_url": "git@github.com:baxterthehacker/public-repo.git", + "clone_url": "https://github.com/baxterthehacker/public-repo.git", + "svn_url": "https://github.com/baxterthehacker/public-repo", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 1, + "forks": 0, + "open_issues": 1, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + } +} diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/push.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/push.json new file mode 100644 index 0000000000..44ba0bbdb1 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/push.json @@ -0,0 +1,174 @@ +{ + "ref": "refs/heads/changes", + "before": "9049f1265b7d61be4a8904a9a27120d2064dab3b", + "after": "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c", + "created": false, + "deleted": false, + "forced": false, + "base_ref": null, + "compare": "https://github.com/baxterthehacker/public-repo/compare/9049f1265b7d...0d1a26e67d8f", + "commits": [ + { + "id": "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c", + "tree_id": "f9d2a07e9488b91af2641b26b9407fe22a451433", + "distinct": true, + "message": "Update README.md", + "timestamp": "2015-05-05T19:40:15-04:00", + "url": "https://github.com/baxterthehacker/public-repo/commit/0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c", + "author": { + "name": "baxterthehacker", + "email": "baxterthehacker@users.noreply.github.com", + "username": "baxterthehacker" + }, + "committer": { + "name": "baxterthehacker", + "email": "baxterthehacker@users.noreply.github.com", + "username": "baxterthehacker" + }, + "added": [ + ], + "removed": [ + ], + "modified": [ + "README.md" + ] + } + ], + "head_commit": { + "id": "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c", + "tree_id": "f9d2a07e9488b91af2641b26b9407fe22a451433", + "distinct": true, + "message": "Update README.md", + "timestamp": "2015-05-05T19:40:15-04:00", + "url": "https://github.com/baxterthehacker/public-repo/commit/0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c", + "author": { + "name": "baxterthehacker", + "email": "baxterthehacker@users.noreply.github.com", + "username": "baxterthehacker" + }, + "committer": { + "name": "baxterthehacker", + "email": "baxterthehacker@users.noreply.github.com", + "username": "baxterthehacker" + }, + "added": [ + ], + "removed": [ + ], + "modified": [ + "README.md" + ] + }, + "repository": { + "id": 35129377, + "name": "public-repo", + "full_name": "baxterthehacker/public-repo", + "owner": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/baxterthehacker/public-repo", + "description": "", + "fork": false, + "url": "https://github.com/baxterthehacker/public-repo", + "forks_url": "https://api.github.com/repos/baxterthehacker/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterthehacker/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterthehacker/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterthehacker/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterthehacker/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterthehacker/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterthehacker/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterthehacker/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterthehacker/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterthehacker/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterthehacker/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/baxterthehacker/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterthehacker/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterthehacker/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterthehacker/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterthehacker/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterthehacker/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterthehacker/public-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterthehacker/public-repo/releases{/id}", + "created_at": 1430869212, + "updated_at": "2015-05-05T23:40:12Z", + "pushed_at": 1430869217, + "git_url": "git://github.com/baxterthehacker/public-repo.git", + "ssh_url": "git@github.com:baxterthehacker/public-repo.git", + "clone_url": "https://github.com/baxterthehacker/public-repo.git", + "svn_url": "https://github.com/baxterthehacker/public-repo", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 0, + "forks": 0, + "open_issues": 0, + "watchers": 0, + "default_branch": "master", + "stargazers": 0, + "master_branch": "master" + }, + "pusher": { + "name": "baxterthehacker", + "email": "baxterthehacker@users.noreply.github.com" + }, + "sender": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + } +} diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/release.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/release.json new file mode 100644 index 0000000000..35de2f33eb --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/release.json @@ -0,0 +1,147 @@ +{ + "action": "published", + "release": { + "url": "https://api.github.com/repos/baxterthehacker/public-repo/releases/1261438", + "assets_url": "https://api.github.com/repos/baxterthehacker/public-repo/releases/1261438/assets", + "upload_url": "https://uploads.github.com/repos/baxterthehacker/public-repo/releases/1261438/assets{?name}", + "html_url": "https://github.com/baxterthehacker/public-repo/releases/tag/0.0.1", + "id": 1261438, + "tag_name": "0.0.1", + "target_commitish": "master", + "name": null, + "draft": false, + "author": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "prerelease": false, + "created_at": "2015-05-05T23:40:12Z", + "published_at": "2015-05-05T23:40:38Z", + "assets": [ + ], + "tarball_url": "https://api.github.com/repos/baxterthehacker/public-repo/tarball/0.0.1", + "zipball_url": "https://api.github.com/repos/baxterthehacker/public-repo/zipball/0.0.1", + "body": null + }, + "repository": { + "id": 35129377, + "name": "public-repo", + "full_name": "baxterthehacker/public-repo", + "owner": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/baxterthehacker/public-repo", + "description": "", + "fork": false, + "url": "https://api.github.com/repos/baxterthehacker/public-repo", + "forks_url": "https://api.github.com/repos/baxterthehacker/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterthehacker/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterthehacker/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterthehacker/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterthehacker/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterthehacker/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterthehacker/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterthehacker/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterthehacker/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterthehacker/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterthehacker/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/baxterthehacker/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterthehacker/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterthehacker/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterthehacker/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterthehacker/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterthehacker/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterthehacker/public-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterthehacker/public-repo/releases{/id}", + "created_at": "2015-05-05T23:40:12Z", + "updated_at": "2015-05-05T23:40:30Z", + "pushed_at": "2015-05-05T23:40:38Z", + "git_url": "git://github.com/baxterthehacker/public-repo.git", + "ssh_url": "git@github.com:baxterthehacker/public-repo.git", + "clone_url": "https://github.com/baxterthehacker/public-repo.git", + "svn_url": "https://github.com/baxterthehacker/public-repo", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 2, + "forks": 0, + "open_issues": 2, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + } +} diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/repository.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/repository.json new file mode 100644 index 0000000000..d22386c3f2 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/repository.json @@ -0,0 +1,119 @@ +{ + "action": "created", + "repository": { + "id": 27496774, + "name": "new-repository", + "full_name": "baxterandthehackers/new-repository", + "owner": { + "login": "baxterandthehackers", + "id": 7649605, + "avatar_url": "https://avatars.githubusercontent.com/u/7649605?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterandthehackers", + "html_url": "https://github.com/baxterandthehackers", + "followers_url": "https://api.github.com/users/baxterandthehackers/followers", + "following_url": "https://api.github.com/users/baxterandthehackers/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterandthehackers/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterandthehackers/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterandthehackers/subscriptions", + "organizations_url": "https://api.github.com/users/baxterandthehackers/orgs", + "repos_url": "https://api.github.com/users/baxterandthehackers/repos", + "events_url": "https://api.github.com/users/baxterandthehackers/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterandthehackers/received_events", + "type": "Organization", + "site_admin": false + }, + "private": true, + "html_url": "https://github.com/baxterandthehackers/new-repository", + "description": "", + "fork": false, + "url": "https://api.github.com/repos/baxterandthehackers/new-repository", + "forks_url": "https://api.github.com/repos/baxterandthehackers/new-repository/forks", + "keys_url": "https://api.github.com/repos/baxterandthehackers/new-repository/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterandthehackers/new-repository/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterandthehackers/new-repository/teams", + "hooks_url": "https://api.github.com/repos/baxterandthehackers/new-repository/hooks", + "issue_events_url": "https://api.github.com/repos/baxterandthehackers/new-repository/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterandthehackers/new-repository/events", + "assignees_url": "https://api.github.com/repos/baxterandthehackers/new-repository/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterandthehackers/new-repository/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterandthehackers/new-repository/tags", + "blobs_url": "https://api.github.com/repos/baxterandthehackers/new-repository/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterandthehackers/new-repository/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterandthehackers/new-repository/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterandthehackers/new-repository/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterandthehackers/new-repository/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterandthehackers/new-repository/languages", + "stargazers_url": "https://api.github.com/repos/baxterandthehackers/new-repository/stargazers", + "contributors_url": "https://api.github.com/repos/baxterandthehackers/new-repository/contributors", + "subscribers_url": "https://api.github.com/repos/baxterandthehackers/new-repository/subscribers", + "subscription_url": "https://api.github.com/repos/baxterandthehackers/new-repository/subscription", + "commits_url": "https://api.github.com/repos/baxterandthehackers/new-repository/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterandthehackers/new-repository/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterandthehackers/new-repository/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterandthehackers/new-repository/issues/comments/{number}", + "contents_url": "https://api.github.com/repos/baxterandthehackers/new-repository/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterandthehackers/new-repository/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterandthehackers/new-repository/merges", + "archive_url": "https://api.github.com/repos/baxterandthehackers/new-repository/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterandthehackers/new-repository/downloads", + "issues_url": "https://api.github.com/repos/baxterandthehackers/new-repository/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterandthehackers/new-repository/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterandthehackers/new-repository/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterandthehackers/new-repository/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/baxterandthehackers/new-repository/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterandthehackers/new-repository/releases{/id}", + "created_at": "2014-12-03T16:39:25Z", + "updated_at": "2014-12-03T16:39:25Z", + "pushed_at": "2014-12-03T16:39:25Z", + "git_url": "git://github.com/baxterandthehackers/new-repository.git", + "ssh_url": "git@github.com:baxterandthehackers/new-repository.git", + "clone_url": "https://github.com/baxterandthehackers/new-repository.git", + "svn_url": "https://github.com/baxterandthehackers/new-repository", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": false, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 0, + "forks": 0, + "open_issues": 0, + "watchers": 0, + "default_branch": "master" + }, + "organization": { + "login": "baxterandthehackers", + "id": 7649605, + "url": "https://api.github.com/orgs/baxterandthehackers", + "repos_url": "https://api.github.com/orgs/baxterandthehackers/repos", + "events_url": "https://api.github.com/orgs/baxterandthehackers/events", + "members_url": "https://api.github.com/orgs/baxterandthehackers/members{/member}", + "public_members_url": "https://api.github.com/orgs/baxterandthehackers/public_members{/member}", + "avatar_url": "https://avatars.githubusercontent.com/u/7649605?v=2" + }, + "sender": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=2", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + } +} diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/status.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/status.json new file mode 100644 index 0000000000..82f5a09967 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/status.json @@ -0,0 +1,205 @@ +{ + "id": 214015194, + "sha": "9049f1265b7d61be4a8904a9a27120d2064dab3b", + "name": "baxterthehacker/public-repo", + "target_url": null, + "context": "default", + "description": null, + "state": "success", + "commit": { + "sha": "9049f1265b7d61be4a8904a9a27120d2064dab3b", + "commit": { + "author": { + "name": "baxterthehacker", + "email": "baxterthehacker@users.noreply.github.com", + "date": "2015-05-05T23:40:12Z" + }, + "committer": { + "name": "baxterthehacker", + "email": "baxterthehacker@users.noreply.github.com", + "date": "2015-05-05T23:40:12Z" + }, + "message": "Initial commit", + "tree": { + "sha": "02b49ad0ba4f1acd9f06531b21e16a4ac5d341d0", + "url": "https://api.github.com/repos/baxterthehacker/public-repo/git/trees/02b49ad0ba4f1acd9f06531b21e16a4ac5d341d0" + }, + "url": "https://api.github.com/repos/baxterthehacker/public-repo/git/commits/9049f1265b7d61be4a8904a9a27120d2064dab3b", + "comment_count": 1 + }, + "url": "https://api.github.com/repos/baxterthehacker/public-repo/commits/9049f1265b7d61be4a8904a9a27120d2064dab3b", + "html_url": "https://github.com/baxterthehacker/public-repo/commit/9049f1265b7d61be4a8904a9a27120d2064dab3b", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/commits/9049f1265b7d61be4a8904a9a27120d2064dab3b/comments", + "author": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "committer": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "parents": [ + ] + }, + "branches": [ + { + "name": "master", + "commit": { + "sha": "9049f1265b7d61be4a8904a9a27120d2064dab3b", + "url": "https://api.github.com/repos/baxterthehacker/public-repo/commits/9049f1265b7d61be4a8904a9a27120d2064dab3b" + } + }, + { + "name": "changes", + "commit": { + "sha": "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c", + "url": "https://api.github.com/repos/baxterthehacker/public-repo/commits/0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c" + } + }, + { + "name": "gh-pages", + "commit": { + "sha": "b11bb7545ac14abafc6191a0481b0d961e7793c6", + "url": "https://api.github.com/repos/baxterthehacker/public-repo/commits/b11bb7545ac14abafc6191a0481b0d961e7793c6" + } + } + ], + "created_at": "2015-05-05T23:40:39Z", + "updated_at": "2015-05-05T23:40:39Z", + "repository": { + "id": 35129377, + "name": "public-repo", + "full_name": "baxterthehacker/public-repo", + "owner": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/baxterthehacker/public-repo", + "description": "", + "fork": false, + "url": "https://api.github.com/repos/baxterthehacker/public-repo", + "forks_url": "https://api.github.com/repos/baxterthehacker/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterthehacker/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterthehacker/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterthehacker/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterthehacker/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterthehacker/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterthehacker/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterthehacker/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterthehacker/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterthehacker/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterthehacker/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/baxterthehacker/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterthehacker/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterthehacker/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterthehacker/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterthehacker/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterthehacker/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterthehacker/public-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterthehacker/public-repo/releases{/id}", + "created_at": "2015-05-05T23:40:12Z", + "updated_at": "2015-05-05T23:40:30Z", + "pushed_at": "2015-05-05T23:40:39Z", + "git_url": "git://github.com/baxterthehacker/public-repo.git", + "ssh_url": "git@github.com:baxterthehacker/public-repo.git", + "clone_url": "https://github.com/baxterthehacker/public-repo.git", + "svn_url": "https://github.com/baxterthehacker/public-repo", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 2, + "forks": 0, + "open_issues": 2, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + } +} diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/team_add.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/team_add.json new file mode 100644 index 0000000000..bd4256bc07 --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/team_add.json @@ -0,0 +1,129 @@ +{ + "team": { + "name": "github", + "id": 836012, + "slug": "github", + "description": "", + "permission": "pull", + "url": "https://api.github.com/teams/836012", + "members_url": "https://api.github.com/teams/836012/members{/member}", + "repositories_url": "https://api.github.com/teams/836012/repos" + }, + "repository": { + "id": 35129393, + "name": "public-repo", + "full_name": "baxterandthehackers/public-repo", + "owner": { + "login": "baxterandthehackers", + "id": 7649605, + "avatar_url": "https://avatars.githubusercontent.com/u/7649605?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterandthehackers", + "html_url": "https://github.com/baxterandthehackers", + "followers_url": "https://api.github.com/users/baxterandthehackers/followers", + "following_url": "https://api.github.com/users/baxterandthehackers/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterandthehackers/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterandthehackers/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterandthehackers/subscriptions", + "organizations_url": "https://api.github.com/users/baxterandthehackers/orgs", + "repos_url": "https://api.github.com/users/baxterandthehackers/repos", + "events_url": "https://api.github.com/users/baxterandthehackers/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterandthehackers/received_events", + "type": "Organization", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/baxterandthehackers/public-repo", + "description": "", + "fork": true, + "url": "https://api.github.com/repos/baxterandthehackers/public-repo", + "forks_url": "https://api.github.com/repos/baxterandthehackers/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterandthehackers/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterandthehackers/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterandthehackers/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterandthehackers/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterandthehackers/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterandthehackers/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterandthehackers/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterandthehackers/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterandthehackers/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterandthehackers/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterandthehackers/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterandthehackers/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterandthehackers/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterandthehackers/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterandthehackers/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterandthehackers/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterandthehackers/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterandthehackers/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterandthehackers/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterandthehackers/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterandthehackers/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterandthehackers/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterandthehackers/public-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/baxterandthehackers/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterandthehackers/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterandthehackers/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterandthehackers/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterandthehackers/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterandthehackers/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterandthehackers/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterandthehackers/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterandthehackers/public-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/baxterandthehackers/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterandthehackers/public-repo/releases{/id}", + "created_at": "2015-05-05T23:40:30Z", + "updated_at": "2015-05-05T23:40:30Z", + "pushed_at": "2015-05-05T23:40:27Z", + "git_url": "git://github.com/baxterandthehackers/public-repo.git", + "ssh_url": "git@github.com:baxterandthehackers/public-repo.git", + "clone_url": "https://github.com/baxterandthehackers/public-repo.git", + "svn_url": "https://github.com/baxterandthehackers/public-repo", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": false, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 0, + "forks": 0, + "open_issues": 0, + "watchers": 0, + "default_branch": "master" + }, + "organization": { + "login": "baxterandthehackers", + "id": 7649605, + "url": "https://api.github.com/orgs/baxterandthehackers", + "repos_url": "https://api.github.com/orgs/baxterandthehackers/repos", + "events_url": "https://api.github.com/orgs/baxterandthehackers/events", + "members_url": "https://api.github.com/orgs/baxterandthehackers/members{/member}", + "public_members_url": "https://api.github.com/orgs/baxterandthehackers/public_members{/member}", + "avatar_url": "https://avatars.githubusercontent.com/u/7649605?v=3", + "description": null + }, + "sender": { + "login": "baxterandthehackers", + "id": 7649605, + "avatar_url": "https://avatars.githubusercontent.com/u/7649605?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterandthehackers", + "html_url": "https://github.com/baxterandthehackers", + "followers_url": "https://api.github.com/users/baxterandthehackers/followers", + "following_url": "https://api.github.com/users/baxterandthehackers/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterandthehackers/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterandthehackers/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterandthehackers/subscriptions", + "organizations_url": "https://api.github.com/users/baxterandthehackers/orgs", + "repos_url": "https://api.github.com/users/baxterandthehackers/repos", + "events_url": "https://api.github.com/users/baxterandthehackers/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterandthehackers/received_events", + "type": "Organization", + "site_admin": false + } +} diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/watch.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/watch.json new file mode 100644 index 0000000000..88bc71d0ab --- /dev/null +++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/watch.json @@ -0,0 +1,109 @@ +{ + "action": "started", + "repository": { + "id": 35129377, + "name": "public-repo", + "full_name": "baxterthehacker/public-repo", + "owner": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/baxterthehacker/public-repo", + "description": "", + "fork": false, + "url": "https://api.github.com/repos/baxterthehacker/public-repo", + "forks_url": "https://api.github.com/repos/baxterthehacker/public-repo/forks", + "keys_url": "https://api.github.com/repos/baxterthehacker/public-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/baxterthehacker/public-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/baxterthehacker/public-repo/teams", + "hooks_url": "https://api.github.com/repos/baxterthehacker/public-repo/hooks", + "issue_events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/baxterthehacker/public-repo/events", + "assignees_url": "https://api.github.com/repos/baxterthehacker/public-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/baxterthehacker/public-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/tags", + "blobs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/baxterthehacker/public-repo/languages", + "stargazers_url": "https://api.github.com/repos/baxterthehacker/public-repo/stargazers", + "contributors_url": "https://api.github.com/repos/baxterthehacker/public-repo/contributors", + "subscribers_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscribers", + "subscription_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscription", + "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/baxterthehacker/public-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/baxterthehacker/public-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/baxterthehacker/public-repo/merges", + "archive_url": "https://api.github.com/repos/baxterthehacker/public-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/baxterthehacker/public-repo/downloads", + "issues_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/baxterthehacker/public-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/baxterthehacker/public-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/baxterthehacker/public-repo/releases{/id}", + "created_at": "2015-05-05T23:40:12Z", + "updated_at": "2015-05-05T23:40:30Z", + "pushed_at": "2015-05-05T23:40:27Z", + "git_url": "git://github.com/baxterthehacker/public-repo.git", + "ssh_url": "git@github.com:baxterthehacker/public-repo.git", + "clone_url": "https://github.com/baxterthehacker/public-repo.git", + "svn_url": "https://github.com/baxterthehacker/public-repo", + "homepage": null, + "size": 0, + "stargazers_count": 0, + "watchers_count": 0, + "language": null, + "has_issues": true, + "has_downloads": true, + "has_wiki": true, + "has_pages": true, + "forks_count": 0, + "mirror_url": null, + "open_issues_count": 2, + "forks": 0, + "open_issues": 2, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "baxterthehacker", + "id": 6752317, + "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "gravatar_id": "", + "url": "https://api.github.com/users/baxterthehacker", + "html_url": "https://github.com/baxterthehacker", + "followers_url": "https://api.github.com/users/baxterthehacker/followers", + "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", + "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", + "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", + "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", + "repos_url": "https://api.github.com/users/baxterthehacker/repos", + "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", + "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", + "type": "User", + "site_admin": false + } +} From 5b92d4b88cafcc6050f875fea6d5116880fa04f8 Mon Sep 17 00:00:00 2001 From: Stephen Connolly Date: Tue, 8 Nov 2016 15:04:02 +0000 Subject: [PATCH 177/390] Fix findbugs false alarms --- src/main/java/org/kohsuke/github/GHCommitComment.java | 10 ---------- src/main/java/org/kohsuke/github/GHEventPayload.java | 4 ++++ 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHCommitComment.java b/src/main/java/org/kohsuke/github/GHCommitComment.java index 64b658d2ff..79f19a6e6b 100644 --- a/src/main/java/org/kohsuke/github/GHCommitComment.java +++ b/src/main/java/org/kohsuke/github/GHCommitComment.java @@ -23,16 +23,6 @@ public class GHCommitComment extends GHObject { String path; GHUser user; // not fully populated. beware. - static class User { - // TODO: what if someone who doesn't have an account on GitHub makes a commit? - @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() { return owner; } diff --git a/src/main/java/org/kohsuke/github/GHEventPayload.java b/src/main/java/org/kohsuke/github/GHEventPayload.java index 7e54646485..2dfbe61dba 100644 --- a/src/main/java/org/kohsuke/github/GHEventPayload.java +++ b/src/main/java/org/kohsuke/github/GHEventPayload.java @@ -428,6 +428,8 @@ void wrapUp(GitHub root) { * * @see authoritative source */ + @SuppressFBWarnings(value = {"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR", "NP_UNWRITTEN_FIELD", "UUF_UNUSED_FIELD"}, + justification = "Constructed by JSON deserialization") public static class Push extends GHEventPayload { private String head, before; private boolean created, deleted, forced; @@ -553,6 +555,8 @@ public List getModified() { * * @see authoritative source */ + @SuppressFBWarnings(value = {"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR", "NP_UNWRITTEN_FIELD", "UWF_UNWRITTEN_FIELD"}, + justification = "Constructed by JSON deserialization") public static class Repository extends GHEventPayload { private String action; private GHRepository repository; From ce3f74232e669dc3ec09b50ef18de8632d86c020 Mon Sep 17 00:00:00 2001 From: Stephen Connolly Date: Tue, 8 Nov 2016 15:11:35 +0000 Subject: [PATCH 178/390] Ensure a use case required by github-plugin is valid --- src/test/java/org/kohsuke/github/GHEventPayloadTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/org/kohsuke/github/GHEventPayloadTest.java b/src/test/java/org/kohsuke/github/GHEventPayloadTest.java index f414b6e7b7..7cdc46cf89 100644 --- a/src/test/java/org/kohsuke/github/GHEventPayloadTest.java +++ b/src/test/java/org/kohsuke/github/GHEventPayloadTest.java @@ -212,6 +212,7 @@ public void push() throws Exception { assertThat(event.getCommits().get(0).getModified().get(0), is("README.md")); assertThat(event.getRepository().getName(), is("public-repo")); assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); + assertThat(event.getRepository().getUrl().toExternalForm(), is("https://github.com/baxterthehacker/public-repo")); assertThat(event.getSender().getLogin(), is("baxterthehacker")); } From 7bf8621afe616c20060b070f01c3fb9cf734e291 Mon Sep 17 00:00:00 2001 From: Stephen Connolly Date: Tue, 8 Nov 2016 15:14:42 +0000 Subject: [PATCH 179/390] Need the pusher details for github-plugin --- .../org/kohsuke/github/GHEventPayload.java | 29 +++++++++++++++++++ .../kohsuke/github/GHEventPayloadTest.java | 2 ++ 2 files changed, 31 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHEventPayload.java b/src/main/java/org/kohsuke/github/GHEventPayload.java index 2dfbe61dba..7f1f4618c1 100644 --- a/src/main/java/org/kohsuke/github/GHEventPayload.java +++ b/src/main/java/org/kohsuke/github/GHEventPayload.java @@ -437,6 +437,7 @@ public static class Push extends GHEventPayload { private int size; private List commits; private GHRepository repository; + private Pusher pusher; /** * The SHA of the HEAD commit on the repository @@ -484,6 +485,14 @@ public GHRepository getRepository() { return repository; } + public Pusher getPusher() { + return pusher; + } + + public void setPusher(Pusher pusher) { + this.pusher = pusher; + } + @Override void wrapUp(GitHub root) { super.wrapUp(root); @@ -491,6 +500,26 @@ void wrapUp(GitHub root) { repository.wrap(root); } + public static class Pusher { + private String name, email; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + } + /** * Commit in a push */ diff --git a/src/test/java/org/kohsuke/github/GHEventPayloadTest.java b/src/test/java/org/kohsuke/github/GHEventPayloadTest.java index 7cdc46cf89..456ea2316c 100644 --- a/src/test/java/org/kohsuke/github/GHEventPayloadTest.java +++ b/src/test/java/org/kohsuke/github/GHEventPayloadTest.java @@ -213,6 +213,8 @@ public void push() throws Exception { assertThat(event.getRepository().getName(), is("public-repo")); assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); assertThat(event.getRepository().getUrl().toExternalForm(), is("https://github.com/baxterthehacker/public-repo")); + assertThat(event.getPusher().getName(), is("baxterthehacker")); + assertThat(event.getPusher().getEmail(), is("baxterthehacker@users.noreply.github.com")); assertThat(event.getSender().getLogin(), is("baxterthehacker")); } From 66145e1d232be7324ea72d93186d9ce4f014736b Mon Sep 17 00:00:00 2001 From: Stephen Connolly Date: Tue, 8 Nov 2016 15:26:33 +0000 Subject: [PATCH 180/390] Seems there is an undocumented but important PING event used by github-plugin --- .../org/kohsuke/github/GHEventPayload.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHEventPayload.java b/src/main/java/org/kohsuke/github/GHEventPayload.java index 7f1f4618c1..bc326fcf2e 100644 --- a/src/main/java/org/kohsuke/github/GHEventPayload.java +++ b/src/main/java/org/kohsuke/github/GHEventPayload.java @@ -398,6 +398,29 @@ void wrapUp(GitHub root) { } } + /** + * A ping. + */ + public static class Ping extends GHEventPayload { + private GHRepository repository; + + public void setRepository(GHRepository repository) { + this.repository = repository; + } + + public GHRepository getRepository() { + return repository; + } + + @Override + void wrapUp(GitHub root) { + super.wrapUp(root); + if (repository!=null) + repository.wrap(root); + } + + } + /** * A repository was made public. * From 7dc620a3ba6b9cee23a077f24f438fa2c1b92333 Mon Sep 17 00:00:00 2001 From: Stephen Connolly Date: Tue, 8 Nov 2016 15:29:27 +0000 Subject: [PATCH 181/390] More details emerge on the PingEvent payload --- src/main/java/org/kohsuke/github/GHEventPayload.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHEventPayload.java b/src/main/java/org/kohsuke/github/GHEventPayload.java index bc326fcf2e..d1ffa97fb5 100644 --- a/src/main/java/org/kohsuke/github/GHEventPayload.java +++ b/src/main/java/org/kohsuke/github/GHEventPayload.java @@ -403,6 +403,7 @@ void wrapUp(GitHub root) { */ public static class Ping extends GHEventPayload { private GHRepository repository; + private GHOrganization organization; public void setRepository(GHRepository repository) { this.repository = repository; @@ -412,11 +413,22 @@ public GHRepository getRepository() { return repository; } + public GHOrganization getOrganization() { + return organization; + } + + public void setOrganization(GHOrganization organization) { + this.organization = organization; + } + @Override void wrapUp(GitHub root) { super.wrapUp(root); if (repository!=null) repository.wrap(root); + if (organization != null) { + organization.wrapUp(root); + } } } From 498d63ea0067621d2271df3592a03c8e24a0443f Mon Sep 17 00:00:00 2001 From: Stephen Connolly Date: Tue, 8 Nov 2016 15:48:39 +0000 Subject: [PATCH 182/390] Typos spotted by Jesse --- src/main/java/org/kohsuke/github/GitHub.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 04b3efefd3..8f2e65ade8 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -216,11 +216,11 @@ public static GitHub connectToEnterpriseAnonymously(String apiUrl) throws IOExce } /** - * An off-line only {@link GitHub} useful for parsing event notification from an unknown source. + * An offline-only {@link GitHub} useful for parsing event notification from an unknown source. * * All operations that require a connection will fail. * - * @return An off-line only {@link GitHub}. + * @return An offline-only {@link GitHub}. */ public static GitHub offline() { try { From d36e145d066466ab0ee7373db1734b744f94aafd Mon Sep 17 00:00:00 2001 From: Stephen Connolly Date: Fri, 11 Nov 2016 14:18:47 +0000 Subject: [PATCH 183/390] Need to be able to tell if this is a creation / deletion of a ref for multibranch projects --- src/main/java/org/kohsuke/github/GHEventPayload.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHEventPayload.java b/src/main/java/org/kohsuke/github/GHEventPayload.java index d1ffa97fb5..29f69bb3eb 100644 --- a/src/main/java/org/kohsuke/github/GHEventPayload.java +++ b/src/main/java/org/kohsuke/github/GHEventPayload.java @@ -509,6 +509,18 @@ public int getSize() { return size; } + public boolean isCreated() { + return created; + } + + public boolean isDeleted() { + return deleted; + } + + public boolean isForced() { + return forced; + } + /** * The list of pushed commits. */ From 9988a090acd96c345d61a24b947e078cca000760 Mon Sep 17 00:00:00 2001 From: Stephen Connolly Date: Fri, 11 Nov 2016 14:27:09 +0000 Subject: [PATCH 184/390] Add some more tests --- src/test/java/org/kohsuke/github/GHEventPayloadTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/java/org/kohsuke/github/GHEventPayloadTest.java b/src/test/java/org/kohsuke/github/GHEventPayloadTest.java index 456ea2316c..356a5a77d8 100644 --- a/src/test/java/org/kohsuke/github/GHEventPayloadTest.java +++ b/src/test/java/org/kohsuke/github/GHEventPayloadTest.java @@ -202,6 +202,9 @@ public void push() throws Exception { assertThat(event.getRef(), is("refs/heads/changes")); assertThat(event.getBefore(), is("9049f1265b7d61be4a8904a9a27120d2064dab3b")); assertThat(event.getHead(), is("0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c")); + assertThat(event.isCreated(), is(false)); + assertThat(event.isDeleted(), is(false)); + assertThat(event.isForced(), is(false)); assertThat(event.getCommits().size(), is(1)); assertThat(event.getCommits().get(0).getSha(), is("0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c")); assertThat(event.getCommits().get(0).getAuthor().getEmail(), is("baxterthehacker@users.noreply.github.com")); From 24f48f668c326910008cba1227ba53c8b8d4bfe9 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 11 Nov 2016 16:56:03 +0200 Subject: [PATCH 185/390] Add portion of auth/application API. (#307) * Add portion of auth/application API. Signed-off-by: Kanstantsin Shautsou * fixup --- .../org/kohsuke/github/GHAuthorization.java | 18 +++++++++ src/main/java/org/kohsuke/github/GitHub.java | 37 +++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHAuthorization.java b/src/main/java/org/kohsuke/github/GHAuthorization.java index b8b7aff19a..ead866bb0b 100644 --- a/src/main/java/org/kohsuke/github/GHAuthorization.java +++ b/src/main/java/org/kohsuke/github/GHAuthorization.java @@ -36,9 +36,14 @@ public class GHAuthorization extends GHObject { private GitHub root; private List scopes; private String token; + private String token_last_eight; + private String hashed_token; private App app; private String note; private String note_url; + private String fingerprint; + //TODO add some user class for https://developer.github.com/v3/oauth_authorizations/#check-an-authorization ? + //private GHUser user; public GitHub getRoot() { return root; @@ -52,6 +57,14 @@ public String getToken() { return token; } + public String getTokenLastEight() { + return token_last_eight; + } + + public String getHashedToken() { + return hashed_token; + } + public URL getAppUrl() { return GitHub.parseURL(app.url); } @@ -82,6 +95,10 @@ public URL getNoteUrl() { return GitHub.parseURL(note_url); } + public String getFingerprint() { + return fingerprint; + } + /*package*/ GHAuthorization wrap(GitHub root) { this.root = root; return this; @@ -92,5 +109,6 @@ public URL getNoteUrl() { private static class App { private String url; private String name; + private String client_id; } } diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index e5bf16b1de..9dcce5fc83 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -58,6 +58,7 @@ import com.fasterxml.jackson.databind.introspect.VisibilityChecker.Std; import com.infradna.tool.bridge_method_injector.WithBridgeMethods; +import javax.annotation.Nonnull; import java.util.logging.Logger; /** @@ -497,6 +498,42 @@ public GHAuthorization createToken(Collection scope, String note, String return requester.method("POST").to("/authorizations", GHAuthorization.class).wrap(this); } + /** + * @see docs + */ + public GHAuthorization createOrGetAuth(String clientId, String clientSecret, List scopes, String note, + String note_url) + throws IOException { + Requester requester = new Requester(this) + .with("client_secret", clientSecret) + .with("scopes", scopes) + .with("note", note) + .with("note_url", note_url); + + return requester.method("PUT").to("/authorizations/clients/" + clientId, GHAuthorization.class); + } + + /** + * @see Delete an authorization + */ + public void deleteAuth(long id) throws IOException { + retrieve().method("DELETE").to("/authorizations/" + id); + } + + /** + * @see Check an authorization + */ + public GHAuthorization checkAuth(@Nonnull String clientId, @Nonnull String accessToken) throws IOException { + return retrieve().to("/applications/" + clientId + "/tokens/" + accessToken, GHAuthorization.class); + } + + /** + * @see Reset an authorization + */ + public GHAuthorization resetAuth(@Nonnull String clientId, @Nonnull String accessToken) throws IOException { + return retrieve().method("POST").to("/applications/" + clientId + "/tokens/" + accessToken, GHAuthorization.class); + } + /** * Ensures that the credential is valid. */ From e544c7a65ae65ff03d45fca4baae1ccaaeed6583 Mon Sep 17 00:00:00 2001 From: Stephen Connolly Date: Mon, 14 Nov 2016 12:52:22 +0000 Subject: [PATCH 186/390] Fix the push event payload --- .../java/org/kohsuke/github/GHRepository.java | 44 ++++++++++--------- .../kohsuke/github/GHEventPayloadTest.java | 2 +- .../github/GHEventPayloadTest/push.json | 19 +------- 3 files changed, 27 insertions(+), 38 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index a26d8e75a6..3cdaab07e7 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -232,7 +232,7 @@ public String getLanguage() { } public GHUser getOwner() throws IOException { - return root.isOffline() ? owner : root.getUser(owner.login); // because 'owner' isn't fully populated + return root.isOffline() ? owner : root.getUser(getOwnerName()); // because 'owner' isn't fully populated } public GHIssue getIssue(int id) throws IOException { @@ -339,7 +339,11 @@ public Map listLanguages() throws IOException { } public String getOwnerName() { - return owner.login; + // consistency of the GitHub API is super... some serialized forms of GHRepository populate + // a full GHUser while others populate only the owner and email. This later form is super helpful + // in putting the login in owner.name not owner.login... thankfully we can easily identify this + // second set because owner.login will be null + return owner.login != null ? owner.login : owner.name; } public boolean hasIssues() { @@ -467,7 +471,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(new HashSet(Arrays.asList(GHTeam.wrapUp(root.retrieve().to(getApiTailUrl("teams"), GHTeam[].class), root.getOrganization(owner.login))))); + return Collections.unmodifiableSet(new HashSet(Arrays.asList(GHTeam.wrapUp(root.retrieve().to(getApiTailUrl("teams"), GHTeam[].class), root.getOrganization(getOwnerName()))))); } public void addCollaborators(GHUser... users) throws IOException { @@ -551,7 +555,7 @@ public void delete() throws IOException { try { new Requester(root).method("DELETE").to(getApiTailUrl("")); } catch (FileNotFoundException x) { - throw (FileNotFoundException) new FileNotFoundException("Failed to delete " + owner.login + "/" + name + "; might not exist, or you might need the delete_repo scope in your token: http://stackoverflow.com/a/19327004/12916").initCause(x); + throw (FileNotFoundException) new FileNotFoundException("Failed to delete " + getOwnerName() + "/" + name + "; might not exist, or you might need the delete_repo scope in your token: http://stackoverflow.com/a/19327004/12916").initCause(x); } } @@ -742,7 +746,7 @@ public GHCompare getCompare(GHBranch id1, GHBranch id2) throws IOException { * @throws IOException on failure communicating with GitHub */ public GHRef[] getRefs() throws IOException { - return GHRef.wrap(root.retrieve().to(String.format("/repos/%s/%s/git/refs", owner.login, name), GHRef[].class), root); + return GHRef.wrap(root.retrieve().to(String.format("/repos/%s/%s/git/refs", getOwnerName(), name), GHRef[].class), root); } /** @@ -752,7 +756,7 @@ public GHRef[] getRefs() throws IOException { * @throws IOException on failure communicating with GitHub, potentially due to an invalid ref type being requested */ public GHRef[] getRefs(String refType) throws IOException { - return GHRef.wrap(root.retrieve().to(String.format("/repos/%s/%s/git/refs/%s", owner.login, name, refType), GHRef[].class),root); + return GHRef.wrap(root.retrieve().to(String.format("/repos/%s/%s/git/refs/%s", getOwnerName(), name, refType), GHRef[].class),root); } /** * Retrive a ref of the given type for the current GitHub repository. @@ -769,7 +773,7 @@ public GHRef getRef(String refName) throws IOException { // FIXME: how about other URL unsafe characters, like space, @, : etc? do we need to be using URLEncoder.encode()? // OTOH, '/' need no escaping refName = refName.replaceAll("#", "%23"); - return root.retrieve().to(String.format("/repos/%s/%s/git/refs/%s", owner.login, name, refName), GHRef.class).wrap(root); + return root.retrieve().to(String.format("/repos/%s/%s/git/refs/%s", getOwnerName(), name, refName), GHRef.class).wrap(root); } /** * Retrive a tree of the given type for the current GitHub repository. @@ -781,7 +785,7 @@ public GHRef getRef(String refName) throws IOException { * 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); + String url = String.format("/repos/%s/%s/git/trees/%s", getOwnerName(), name, sha); return root.retrieve().to(url, GHTree.class).wrap(root); } @@ -796,7 +800,7 @@ public GHTree getTree(String sha) throws IOException { * 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); + String url = String.format("/repos/%s/%s/git/trees/%s?recursive=%d", getOwnerName(), name, sha, recursive); return root.retrieve().to(url, GHTree.class).wrap(root); } @@ -806,7 +810,7 @@ public GHTree getTreeRecursive(String sha, int recursive) throws IOException { public GHCommit getCommit(String sha1) throws IOException { GHCommit c = commits.get(sha1); if (c==null) { - c = root.retrieve().to(String.format("/repos/%s/%s/commits/%s", owner.login, name, sha1), GHCommit.class).wrapUp(this); + c = root.retrieve().to(String.format("/repos/%s/%s/commits/%s", getOwnerName(), name, sha1), GHCommit.class).wrapUp(this); commits.put(sha1,c); } return c; @@ -818,7 +822,7 @@ public GHCommit getCommit(String sha1) throws IOException { public PagedIterable listCommits() { return new PagedIterable() { public PagedIterator _iterator(int pageSize) { - return new PagedIterator(root.retrieve().asIterator(String.format("/repos/%s/%s/commits", owner.login, name), GHCommit[].class, pageSize)) { + return new PagedIterator(root.retrieve().asIterator(String.format("/repos/%s/%s/commits", getOwnerName(), name), GHCommit[].class, pageSize)) { protected void wrapUp(GHCommit[] page) { for (GHCommit c : page) c.wrapUp(GHRepository.this); @@ -841,7 +845,7 @@ public GHCommitQueryBuilder queryCommits() { public PagedIterable listCommitComments() { return new PagedIterable() { public PagedIterator _iterator(int pageSize) { - return new PagedIterator(root.retrieve().asIterator(String.format("/repos/%s/%s/comments", owner.login, name), GHCommitComment[].class, pageSize)) { + return new PagedIterator(root.retrieve().asIterator(String.format("/repos/%s/%s/comments", getOwnerName(), name), GHCommitComment[].class, pageSize)) { @Override protected void wrapUp(GHCommitComment[] page) { for (GHCommitComment c : page) @@ -898,7 +902,7 @@ private GHContentWithLicense getLicenseContent_() throws IOException { public PagedIterable listCommitStatuses(final String sha1) throws IOException { return new PagedIterable() { public PagedIterator _iterator(int pageSize) { - return new PagedIterator(root.retrieve().asIterator(String.format("/repos/%s/%s/statuses/%s", owner.login, name, sha1), GHCommitStatus[].class, pageSize)) { + return new PagedIterator(root.retrieve().asIterator(String.format("/repos/%s/%s/statuses/%s", getOwnerName(), name, sha1), GHCommitStatus[].class, pageSize)) { @Override protected void wrapUp(GHCommitStatus[] page) { for (GHCommitStatus c : page) @@ -933,7 +937,7 @@ public GHCommitStatus createCommitStatus(String sha1, GHCommitState state, Strin .with("target_url", targetUrl) .with("description", description) .with("context", context) - .to(String.format("/repos/%s/%s/statuses/%s",owner.login,this.name,sha1),GHCommitStatus.class).wrapUp(root); + .to(String.format("/repos/%s/%s/statuses/%s",getOwnerName(),this.name,sha1),GHCommitStatus.class).wrapUp(root); } /** @@ -949,7 +953,7 @@ public GHCommitStatus createCommitStatus(String sha1, GHCommitState state, Strin public PagedIterable listEvents() throws IOException { return new PagedIterable() { public PagedIterator _iterator(int pageSize) { - return new PagedIterator(root.retrieve().asIterator(String.format("/repos/%s/%s/events", owner.login, name), GHEventInfo[].class, pageSize)) { + return new PagedIterator(root.retrieve().asIterator(String.format("/repos/%s/%s/events", getOwnerName(), name), GHEventInfo[].class, pageSize)) { @Override protected void wrapUp(GHEventInfo[] page) { for (GHEventInfo c : page) @@ -1076,8 +1080,8 @@ public GHHook createWebHook(URL url) throws IOException { // } private void verifyMine() throws IOException { - if (!root.login.equals(owner.login)) - throw new IOException("Operation not applicable to a repository owned by someone else: "+owner.login); + if (!root.login.equals(getOwnerName())) + throw new IOException("Operation not applicable to a repository owned by someone else: " + getOwnerName()); } /** @@ -1425,14 +1429,14 @@ public GHNotificationStream listNotifications() { @Override public int hashCode() { - return ("Repository:"+owner.login+":"+name).hashCode(); + return ("Repository:"+getOwnerName()+":"+name).hashCode(); } @Override public boolean equals(Object obj) { if (obj instanceof GHRepository) { GHRepository that = (GHRepository) obj; - return this.owner.login.equals(that.owner.login) + return this.getOwnerName().equals(that.getOwnerName()) && this.name.equals(that.name); } return false; @@ -1440,6 +1444,6 @@ public boolean equals(Object obj) { String getApiTailUrl(String tail) { if (tail.length()>0 && !tail.startsWith("/")) tail='/'+tail; - return "/repos/" + owner.login + "/" + name +tail; + return "/repos/" + getOwnerName() + "/" + name +tail; } } diff --git a/src/test/java/org/kohsuke/github/GHEventPayloadTest.java b/src/test/java/org/kohsuke/github/GHEventPayloadTest.java index 356a5a77d8..07758d1a03 100644 --- a/src/test/java/org/kohsuke/github/GHEventPayloadTest.java +++ b/src/test/java/org/kohsuke/github/GHEventPayloadTest.java @@ -214,7 +214,7 @@ public void push() throws Exception { assertThat(event.getCommits().get(0).getModified().size(), is(1)); assertThat(event.getCommits().get(0).getModified().get(0), is("README.md")); assertThat(event.getRepository().getName(), is("public-repo")); - assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); + assertThat(event.getRepository().getOwnerName(), is("baxterthehacker")); assertThat(event.getRepository().getUrl().toExternalForm(), is("https://github.com/baxterthehacker/public-repo")); assertThat(event.getPusher().getName(), is("baxterthehacker")); assertThat(event.getPusher().getEmail(), is("baxterthehacker@users.noreply.github.com")); diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/push.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/push.json index 44ba0bbdb1..11477e0bb7 100644 --- a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/push.json +++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/push.json @@ -64,23 +64,8 @@ "name": "public-repo", "full_name": "baxterthehacker/public-repo", "owner": { - "login": "baxterthehacker", - "id": 6752317, - "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", - "gravatar_id": "", - "url": "https://api.github.com/users/baxterthehacker", - "html_url": "https://github.com/baxterthehacker", - "followers_url": "https://api.github.com/users/baxterthehacker/followers", - "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", - "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", - "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", - "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", - "repos_url": "https://api.github.com/users/baxterthehacker/repos", - "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", - "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", - "type": "User", - "site_admin": false + "name": "baxterthehacker", + "email": "baxterthehacker@users.noreply.github.com" }, "private": false, "html_url": "https://github.com/baxterthehacker/public-repo", From def3a28fb5ef091d69a0057ef6eee2a32d9e610a Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 16 Nov 2016 18:18:45 -0800 Subject: [PATCH 187/390] Restoring backward compatibility of names --- src/main/java/org/kohsuke/github/GHRepository.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index f595bf632e..f98d9380c9 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -358,7 +358,7 @@ public boolean isFork() { * 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 getForksCount() { + public int getForks() { return forks_count; } @@ -378,7 +378,7 @@ public boolean hasPages() { return has_pages; } - public int getWatchersCount() { + public int getWatchers() { return watchers_count; } @@ -386,6 +386,15 @@ public int getOpenIssueCount() { return open_issues_count; } + /** + * @deprecated + * This no longer exists in the official API documentation. + * Use {@link #getForks()} + */ + public int getNetworkCount() { + return forks_count; + } + public int getSubscribersCount() { return subscribers_count; } From 818f6dc045c3fc30dcc19bd5d0250e889e9c0ba0 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 16 Nov 2016 18:26:43 -0800 Subject: [PATCH 188/390] Issue #309: Added user listing --- src/main/java/org/kohsuke/github/GitHub.java | 17 +++++++++++++++++ .../java/org/kohsuke/github/GitHubTest.java | 11 +++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index cb446e1fe0..2a54626f2d 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -392,6 +392,23 @@ protected void wrapUp(GHLicense[] page) { }; } + /** + * Returns a list of all users. + */ + public PagedIterable listUsers() throws IOException { + return new PagedIterable() { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(retrieve().asIterator("/users", GHUser[].class, pageSize)) { + @Override + protected void wrapUp(GHUser[] page) { + for (GHUser u : page) + u.wrapUp(GitHub.this); + } + }; + } + }; + } + /** * Returns the full details for a license * diff --git a/src/test/java/org/kohsuke/github/GitHubTest.java b/src/test/java/org/kohsuke/github/GitHubTest.java index fe6faefac5..010adc8b24 100644 --- a/src/test/java/org/kohsuke/github/GitHubTest.java +++ b/src/test/java/org/kohsuke/github/GitHubTest.java @@ -7,6 +7,8 @@ import java.util.HashMap; import java.util.Map; +import com.google.common.collect.Iterables; +import com.google.common.collect.Iterators; import org.junit.Test; import static org.hamcrest.CoreMatchers.notNullValue; @@ -145,4 +147,13 @@ public void testGitHubIsApiUrlValid() throws IOException { assertTrue(ioe.getMessage().contains("private mode enabled")); } } + + @Test + public void listUsers() throws IOException { + GitHub hub = GitHub.connect(); + for (GHUser u : Iterables.limit(hub.listUsers(),10)) { + assert u.getName()!=null; + System.out.println(u.getName()); + } + } } From 85aa2ad4e6df8dba05950154b6e4e496891b7e78 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 16 Nov 2016 19:10:37 -0800 Subject: [PATCH 189/390] Added reaction API --- .../org/kohsuke/github/GHCommitComment.java | 27 ++++++++- src/main/java/org/kohsuke/github/GHIssue.java | 27 ++++++++- .../org/kohsuke/github/GHIssueComment.java | 29 +++++++++- .../github/GHPullRequestReviewComment.java | 27 ++++++++- .../java/org/kohsuke/github/GHReaction.java | 55 +++++++++++++++++++ .../java/org/kohsuke/github/Previews.java | 1 + .../java/org/kohsuke/github/Reactable.java | 23 ++++++++ .../org/kohsuke/github/ReactionContent.java | 40 ++++++++++++++ src/test/java/org/kohsuke/github/AppTest.java | 15 +++++ 9 files changed, 239 insertions(+), 5 deletions(-) create mode 100644 src/main/java/org/kohsuke/github/GHReaction.java create mode 100644 src/main/java/org/kohsuke/github/Reactable.java create mode 100644 src/main/java/org/kohsuke/github/ReactionContent.java diff --git a/src/main/java/org/kohsuke/github/GHCommitComment.java b/src/main/java/org/kohsuke/github/GHCommitComment.java index 79f19a6e6b..3543b5fdb3 100644 --- a/src/main/java/org/kohsuke/github/GHCommitComment.java +++ b/src/main/java/org/kohsuke/github/GHCommitComment.java @@ -5,6 +5,8 @@ import java.net.URL; import java.util.Date; +import static org.kohsuke.github.Previews.SQUIRREL_GIRL; + /** * A comment attached to a commit (or a specific line in a specific file of a commit.) * @@ -15,7 +17,7 @@ */ @SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD"}, justification = "JSON API") -public class GHCommitComment extends GHObject { +public class GHCommitComment extends GHObject implements Reactable { private GHRepository owner; String body, html_url, commit_id; @@ -86,6 +88,29 @@ public void update(String body) throws IOException { this.body = body; } + @Preview @Deprecated + public GHReaction createReaction(ReactionContent content) throws IOException { + return new Requester(owner.root) + .withPreview(SQUIRREL_GIRL) + .with("content", content.getContent()) + .to(getApiTail()+"/reactions", GHReaction.class).wrap(owner.root); + } + + @Preview @Deprecated + public PagedIterable listReactions() { + return new PagedIterable() { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(owner.root.retrieve().withPreview(SQUIRREL_GIRL).asIterator(getApiTail()+"/reactions", GHReaction[].class, pageSize)) { + @Override + protected void wrapUp(GHReaction[] page) { + for (GHReaction c : page) + c.wrap(owner.root); + } + }; + } + }; + } + /** * Deletes this comment. */ diff --git a/src/main/java/org/kohsuke/github/GHIssue.java b/src/main/java/org/kohsuke/github/GHIssue.java index a5afad6d2e..f02439daa7 100644 --- a/src/main/java/org/kohsuke/github/GHIssue.java +++ b/src/main/java/org/kohsuke/github/GHIssue.java @@ -35,6 +35,8 @@ import java.util.List; import java.util.Locale; +import static org.kohsuke.github.Previews.SQUIRREL_GIRL; + /** * Represents an issue on GitHub. * @@ -44,7 +46,7 @@ * @see GitHub#searchIssues() * @see GHIssueSearchBuilder */ -public class GHIssue extends GHObject { +public class GHIssue extends GHObject implements Reactable{ GitHub root; GHRepository owner; @@ -217,6 +219,29 @@ protected void wrapUp(GHIssueComment[] page) { }; } + @Preview @Deprecated + public GHReaction createReaction(ReactionContent content) throws IOException { + return new Requester(owner.root) + .withPreview(SQUIRREL_GIRL) + .with("content", content.getContent()) + .to(getApiRoute()+"/reactions", GHReaction.class).wrap(root); + } + + @Preview @Deprecated + public PagedIterable listReactions() { + return new PagedIterable() { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(owner.root.retrieve().withPreview(SQUIRREL_GIRL).asIterator(getApiRoute()+"/reactions", GHReaction[].class, pageSize)) { + @Override + protected void wrapUp(GHReaction[] page) { + for (GHReaction c : page) + c.wrap(owner.root); + } + }; + } + }; + } + protected String getApiRoute() { return getIssuesApiRoute(); } diff --git a/src/main/java/org/kohsuke/github/GHIssueComment.java b/src/main/java/org/kohsuke/github/GHIssueComment.java index 18d08bc7f4..a98f6f6398 100644 --- a/src/main/java/org/kohsuke/github/GHIssueComment.java +++ b/src/main/java/org/kohsuke/github/GHIssueComment.java @@ -26,12 +26,14 @@ import java.io.IOException; import java.net.URL; +import static org.kohsuke.github.Previews.SQUIRREL_GIRL; + /** * Comment to the issue * * @author Kohsuke Kawaguchi */ -public class GHIssueComment extends GHObject { +public class GHIssueComment extends GHObject implements Reactable { GHIssue owner; private String body, gravatar_id; @@ -93,7 +95,30 @@ public void update(String body) throws IOException { public void delete() throws IOException { new Requester(owner.root).method("DELETE").to(getApiRoute()); } - + + @Preview @Deprecated + public GHReaction createReaction(ReactionContent content) throws IOException { + return new Requester(owner.root) + .withPreview(SQUIRREL_GIRL) + .with("content", content.getContent()) + .to(getApiRoute()+"/reactions", GHReaction.class).wrap(owner.root); + } + + @Preview @Deprecated + public PagedIterable listReactions() { + return new PagedIterable() { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(owner.root.retrieve().withPreview(SQUIRREL_GIRL).asIterator(getApiRoute()+"/reactions", GHReaction[].class, pageSize)) { + @Override + protected void wrapUp(GHReaction[] page) { + for (GHReaction c : page) + c.wrap(owner.root); + } + }; + } + }; + } + private String getApiRoute() { return "/repos/"+owner.getRepository().getOwnerName()+"/"+owner.getRepository().getName()+"/issues/comments/" + id; } diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java b/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java index 8cb497e16a..05784b5078 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java @@ -26,6 +26,8 @@ import java.io.IOException; import java.net.URL; +import static org.kohsuke.github.Previews.*; + /** * Review comment to the pull request * @@ -33,7 +35,7 @@ * @see GHPullRequest#listReviewComments() * @see GHPullRequest#createReviewComment(String, String, String, int) */ -public class GHPullRequestReviewComment extends GHObject { +public class GHPullRequestReviewComment extends GHObject implements Reactable { GHPullRequest owner; private String body; @@ -103,4 +105,27 @@ public void update(String body) throws IOException { public void delete() throws IOException { new Requester(owner.root).method("DELETE").to(getApiRoute()); } + + @Preview @Deprecated + public GHReaction createReaction(ReactionContent content) throws IOException { + return new Requester(owner.root) + .withPreview(SQUIRREL_GIRL) + .with("content", content.getContent()) + .to(getApiRoute()+"/reactions", GHReaction.class).wrap(owner.root); + } + + @Preview @Deprecated + public PagedIterable listReactions() { + return new PagedIterable() { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(owner.root.retrieve().withPreview(SQUIRREL_GIRL).asIterator(getApiRoute()+"/reactions", GHReaction[].class, pageSize)) { + @Override + protected void wrapUp(GHReaction[] page) { + for (GHReaction c : page) + c.wrap(owner.root); + } + }; + } + }; + } } diff --git a/src/main/java/org/kohsuke/github/GHReaction.java b/src/main/java/org/kohsuke/github/GHReaction.java new file mode 100644 index 0000000000..55b26365e0 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHReaction.java @@ -0,0 +1,55 @@ +package org.kohsuke.github; + +import java.io.IOException; +import java.net.URL; + +import static org.kohsuke.github.Previews.SQUIRREL_GIRL; + +/** + * Reaction to issue, comment, PR, and so on. + * + * @author Kohsuke Kawaguchi + * @see Reactable + */ +@Preview @Deprecated +public class GHReaction extends GHObject { + private GitHub root; + + private GHUser user; + private ReactionContent content; + + /*package*/ GHReaction wrap(GitHub root) { + this.root = root; + user.wrapUp(root); + return this; + } + + /** + * The kind of reaction left. + */ + public ReactionContent getContent() { + return content; + } + + /** + * User who left the reaction. + */ + public GHUser getUser() { + return user; + } + + /** + * Reaction has no HTML URL. Don't call this method. + */ + @Deprecated + public URL getHtmlUrl() { + return null; + } + + /** + * Removes this reaction. + */ + public void delete() throws IOException { + new Requester(root).method("DELETE").withPreview(SQUIRREL_GIRL).to("/reactions/"+id); + } +} diff --git a/src/main/java/org/kohsuke/github/Previews.java b/src/main/java/org/kohsuke/github/Previews.java index a5d061cbd4..f95a28b42b 100644 --- a/src/main/java/org/kohsuke/github/Previews.java +++ b/src/main/java/org/kohsuke/github/Previews.java @@ -6,4 +6,5 @@ /*package*/ class Previews { static final String LOKI = "application/vnd.github.loki-preview+json"; static final String DRAX = "application/vnd.github.drax-preview+json"; + static final String SQUIRREL_GIRL = "application/vnd.github.squirrel-girl-preview"; } diff --git a/src/main/java/org/kohsuke/github/Reactable.java b/src/main/java/org/kohsuke/github/Reactable.java new file mode 100644 index 0000000000..d8821362cf --- /dev/null +++ b/src/main/java/org/kohsuke/github/Reactable.java @@ -0,0 +1,23 @@ +package org.kohsuke.github; + +import java.io.IOException; + +/** + * Those {@link GHObject}s that can have {@linkplain GHReaction reactions}. + * + * @author Kohsuke Kawaguchi + */ +@Preview @Deprecated +public interface Reactable { + /** + * List all the reactions left to this object. + */ + @Preview @Deprecated + PagedIterable listReactions(); + + /** + * Leaves a reaction to this object. + */ + @Preview @Deprecated + GHReaction createReaction(ReactionContent content) throws IOException; +} diff --git a/src/main/java/org/kohsuke/github/ReactionContent.java b/src/main/java/org/kohsuke/github/ReactionContent.java new file mode 100644 index 0000000000..57a204b56d --- /dev/null +++ b/src/main/java/org/kohsuke/github/ReactionContent.java @@ -0,0 +1,40 @@ +package org.kohsuke.github; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Content of reactions. + * + * @author Kohsuke Kawaguchi + * @see API documentation + * @see GHReaction + */ +public enum ReactionContent { + PLUS_ONE("+1"), + MINUS_ONE("-1"), + LAUGH("laugh"), + CONFUSED("confused"), + HEART("heart"), + HOORAY("hooray"); + + private final String content; + + ReactionContent(String content) { + this.content = content; + } + + @JsonValue + public String getContent() { + return content; + } + + @JsonCreator + public static ReactionContent forContent(String content) { + for (ReactionContent c : ReactionContent.values()) { + if (c.getContent().equals(content)) + return c; + } + return null; + } +} diff --git a/src/test/java/org/kohsuke/github/AppTest.java b/src/test/java/org/kohsuke/github/AppTest.java index 5a27582573..15f4ba9c76 100755 --- a/src/test/java/org/kohsuke/github/AppTest.java +++ b/src/test/java/org/kohsuke/github/AppTest.java @@ -870,6 +870,21 @@ public void checkToString() throws Exception { System.out.println(r.getIssue(1)); } + @Test + public void reactions() throws Exception { + GHIssue i = gitHub.getRepository("kohsuke/github-api").getIssue(311); + + // retrieval + GHReaction r = i.listReactions().iterator().next(); + assert r.getUser().getName().equals("kohsuke"); + assert r.getContent()==ReactionContent.HEART; + + // CRUD + GHReaction a = i.createReaction(ReactionContent.HOORAY); + assert a.getUser().equals(gitHub.getMyself()); + a.delete(); + } + private void kohsuke() { String login = getUser().getLogin(); Assume.assumeTrue(login.equals("kohsuke") || login.equals("kohsuke2")); From 18e797095fc3eaaabf8d933b8810a9dd1fa27cbc Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 16 Nov 2016 22:36:16 -0800 Subject: [PATCH 190/390] rewrote assert with JUnit ones --- src/test/java/org/kohsuke/github/AppTest.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/test/java/org/kohsuke/github/AppTest.java b/src/test/java/org/kohsuke/github/AppTest.java index 15f4ba9c76..7246781127 100755 --- a/src/test/java/org/kohsuke/github/AppTest.java +++ b/src/test/java/org/kohsuke/github/AppTest.java @@ -5,6 +5,7 @@ import com.google.common.collect.Lists; import org.apache.commons.io.IOUtils; +import org.hamcrest.CoreMatchers; import org.junit.Assume; import org.junit.Test; import org.kohsuke.github.GHCommit.File; @@ -17,6 +18,8 @@ import java.util.concurrent.ExecutionException; import java.util.regex.Pattern; +import static org.hamcrest.CoreMatchers.*; + /** * Unit test for simple App. */ @@ -876,12 +879,12 @@ public void reactions() throws Exception { // retrieval GHReaction r = i.listReactions().iterator().next(); - assert r.getUser().getName().equals("kohsuke"); - assert r.getContent()==ReactionContent.HEART; + assertThat(r.getUser().getLogin(), is("kohsuke")); + assertThat(r.getContent(),is(ReactionContent.HEART)); // CRUD GHReaction a = i.createReaction(ReactionContent.HOORAY); - assert a.getUser().equals(gitHub.getMyself()); + assertThat(a.getUser().getLogin(),is(gitHub.getMyself().getLogin())); a.delete(); } From 129651479412362a4cbbc9e7b93e579e43d39b9e Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 16 Nov 2016 22:49:13 -0800 Subject: [PATCH 191/390] this field is not yet used --- src/main/java/org/kohsuke/github/GHAuthorization.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHAuthorization.java b/src/main/java/org/kohsuke/github/GHAuthorization.java index ead866bb0b..2a9fa39092 100644 --- a/src/main/java/org/kohsuke/github/GHAuthorization.java +++ b/src/main/java/org/kohsuke/github/GHAuthorization.java @@ -109,6 +109,6 @@ public String getFingerprint() { private static class App { private String url; private String name; - private String client_id; + // private String client_id; not yet used } } From b0e0f045f858156d24100e5e78751afe54040789 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 16 Nov 2016 22:52:10 -0800 Subject: [PATCH 192/390] [maven-release-plugin] prepare release github-api-1.80 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 8d018c1a2f..97328ce89a 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.80-SNAPSHOT + 1.80 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - HEAD + github-api-1.80 From c7f2228a44aaee340ac0796842cf80d3d66f7140 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 16 Nov 2016 22:52:14 -0800 Subject: [PATCH 193/390] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 97328ce89a..cd302f7cd8 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.80 + 1.81-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - github-api-1.80 + HEAD From 47fc813027055cc5b8b53c12828eb650d684e9f1 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 19 Nov 2016 14:29:27 -0800 Subject: [PATCH 194/390] Assignees of the repository. (Personally this concept makes no sense for me, so I don't know what this API really does. I'm just following their API docs) --- .../java/org/kohsuke/github/GHRepository.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index fdd39b8d45..cc25c86004 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -469,6 +469,21 @@ protected void wrapUp(GHUser[] users) { } + /** + * Lists all the available assignees + * to which issues may be assigned. + */ + public PagedIterable listAssignees() throws IOException { + return listUsers("assignees"); + } + + /** + * Checks if the given user is an assignee for this repository. + */ + public boolean hasAssignee(GHUser u) throws IOException { + return root.retrieve().asHttpStatusCode(getApiTailUrl("assignees/" + u.getLogin()))/100==2; + } + /** * Gets the names of the collaborators on this repository. * This method deviates from the principle of this library but it works a lot faster than {@link #getCollaborators()}. From b8bfddbf3a523557c97d3bafddca50102b53e982 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 19 Nov 2016 14:30:35 -0800 Subject: [PATCH 195/390] Code simplification --- .../java/org/kohsuke/github/GHRepository.java | 21 +++---------------- 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index cc25c86004..f34ea85004 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -50,8 +50,8 @@ import java.util.Set; import java.util.TreeMap; -import static java.util.Arrays.asList; -import static org.kohsuke.github.Previews.DRAX; +import static java.util.Arrays.*; +import static org.kohsuke.github.Previews.*; /** * A repository on GitHub. @@ -451,22 +451,7 @@ public GHPersonSet getCollaborators() throws IOException { * @throws IOException */ public PagedIterable listCollaborators() throws IOException { - return new PagedIterable() { - public PagedIterator _iterator(int pageSize) { - - return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("collaborators"), GHUser[].class, pageSize)) { - - @Override - protected void wrapUp(GHUser[] users) { - for (GHUser user : users) { - user.wrapUp(root); - } - } - }; - - } - }; - + return listUsers("collaborators"); } /** From a1528a1a63ced24f6f042a1e0b5bfba368f16950 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 19 Nov 2016 14:48:43 -0800 Subject: [PATCH 196/390] API to add/set/remove assignees from an issue --- src/main/java/org/kohsuke/github/GHIssue.java | 50 +++++++++++++++++-- .../java/org/kohsuke/github/Requester.java | 15 +++++- 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHIssue.java b/src/main/java/org/kohsuke/github/GHIssue.java index f02439daa7..849d4831ff 100644 --- a/src/main/java/org/kohsuke/github/GHIssue.java +++ b/src/main/java/org/kohsuke/github/GHIssue.java @@ -29,13 +29,15 @@ 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.Date; import java.util.List; import java.util.Locale; -import static org.kohsuke.github.Previews.SQUIRREL_GIRL; +import static org.kohsuke.github.Previews.*; /** * Represents an issue on GitHub. @@ -51,7 +53,8 @@ public class GHIssue extends GHObject implements Reactable{ GHRepository owner; // API v3 - protected GHUser assignee; + protected GHUser assignee; // not sure what this field is now that 'assignees' exist + protected GHUser[] assignees; protected String state; protected int number; protected String closed_at; @@ -81,6 +84,7 @@ public static class Label extends GHLabel { /*package*/ GHIssue wrap(GitHub root) { this.root = root; if(assignee != null) assignee.wrapUp(root); + if(assignees!=null) GHUser.wrap(assignees,root); if(user != null) user.wrapUp(root); if(closed_by != null) closed_by.wrapUp(root); return this; @@ -187,7 +191,7 @@ public void setBody(String body) throws IOException { } public void assignTo(GHUser user) throws IOException { - editIssue("assignee", user.getLogin()); + setAssignees(user); } public void setLabels(String... labels) throws IOException { @@ -242,6 +246,40 @@ protected void wrapUp(GHReaction[] page) { }; } + public void addAssignees(GHUser... assignees) throws IOException { + addAssignees(Arrays.asList(assignees)); + } + + public void addAssignees(Collection assignees) throws IOException { + List names = toLogins(assignees); + root.retrieve().method("POST").with("assignees",names).to(getIssuesApiRoute()+"/assignees",this); + } + + public void setAssignees(GHUser... assignees) throws IOException { + setAssignees(Arrays.asList(assignees)); + } + + public void setAssignees(Collection assignees) throws IOException { + editIssue("assignees",toLogins(assignees)); + } + + public void removeAssignees(GHUser... assignees) throws IOException { + removeAssignees(Arrays.asList(assignees)); + } + + public void removeAssignees(Collection assignees) throws IOException { + List names = toLogins(assignees); + root.retrieve().method("DELETE").with("assignees",names).inBody().to(getIssuesApiRoute()+"/assignees",this); + } + + private List toLogins(Collection assignees) { + List names = new ArrayList(assignees.size()); + for (GHUser a : assignees) { + names.add(a.getLogin()); + } + return names; + } + protected String getApiRoute() { return getIssuesApiRoute(); } @@ -253,7 +291,11 @@ protected String getIssuesApiRoute() { public GHUser getAssignee() { return assignee; } - + + public List getAssignees() { + return Collections.unmodifiableList(Arrays.asList(assignees)); + } + /** * User who submitted the issue. */ diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index 6175191ea6..3d240abd65 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -81,6 +81,7 @@ class Requester { * Current connection. */ private HttpURLConnection uc; + private boolean forceBody; private static class Entry { String key; @@ -197,6 +198,16 @@ public Requester contentType(String contentType) { return this; } + /** + * Small number of GitHub APIs use HTTP methods somewhat inconsistently, and use a body where it's not expected. + * Normally whether parameters go as query parameters or a body depends on the HTTP verb in use, + * but this method forces the parameters to be sent as a body. + */ + /*package*/ Requester inBody() { + forceBody = true; + return this; + } + public void to(String tailApiUrl) throws IOException { to(tailApiUrl,null); } @@ -230,7 +241,7 @@ public T to(String tailApiUrl, Class type, String method) throws IOExcept @SuppressFBWarnings("SBSC_USE_STRINGBUFFER_CONCATENATION") private T _to(String tailApiUrl, Class type, T instance) throws IOException { - if (METHODS_WITHOUT_BODY.contains(method) && !args.isEmpty()) { + if (!isMethodWithBody() && !args.isEmpty()) { boolean questionMarkFound = tailApiUrl.indexOf('?') != -1; tailApiUrl += questionMarkFound ? '&' : '?'; for (Iterator it = args.listIterator(); it.hasNext();) { @@ -340,7 +351,7 @@ private void buildRequest() throws IOException { } private boolean isMethodWithBody() { - return !METHODS_WITHOUT_BODY.contains(method); + return forceBody || !METHODS_WITHOUT_BODY.contains(method); } /** From 3f223b1ba079882d16303595a215457d08a5a3b6 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 19 Nov 2016 14:50:47 -0800 Subject: [PATCH 197/390] Support assignees when creating a new issue --- src/main/java/org/kohsuke/github/GHIssueBuilder.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHIssueBuilder.java b/src/main/java/org/kohsuke/github/GHIssueBuilder.java index 385fcd04a0..3a5a532308 100644 --- a/src/main/java/org/kohsuke/github/GHIssueBuilder.java +++ b/src/main/java/org/kohsuke/github/GHIssueBuilder.java @@ -11,6 +11,7 @@ public class GHIssueBuilder { private final GHRepository repo; private final Requester builder; private List labels = new ArrayList(); + private List assignees = new ArrayList(); GHIssueBuilder(GHRepository repo, String title) { this.repo = repo; @@ -28,13 +29,13 @@ public GHIssueBuilder body(String str) { public GHIssueBuilder assignee(GHUser user) { if (user!=null) - builder.with("assignee",user.getLogin()); + assignees.add(user.getLogin()); return this; } public GHIssueBuilder assignee(String user) { if (user!=null) - builder.with("assignee",user); + assignees.add(user); return this; } @@ -54,6 +55,6 @@ public GHIssueBuilder label(String label) { * Creates a new issue. */ public GHIssue create() throws IOException { - return builder.with("labels",labels).to(repo.getApiTailUrl("issues"),GHIssue.class).wrap(repo); + return builder.with("labels",labels).with("assignees",assignees).to(repo.getApiTailUrl("issues"),GHIssue.class).wrap(repo); } } From 511f156603500f659e86343add60496ebd50fb11 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 19 Nov 2016 15:26:04 -0800 Subject: [PATCH 198/390] Added the membership API for the authenticated user. --- .../java/org/kohsuke/github/GHMembership.java | 84 +++++++++++++++++++ .../java/org/kohsuke/github/GHMyself.java | 33 ++++++++ src/main/java/org/kohsuke/github/GHUser.java | 5 ++ src/main/java/org/kohsuke/github/GitHub.java | 2 +- src/test/java/org/kohsuke/github/AppTest.java | 15 ++++ 5 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/kohsuke/github/GHMembership.java diff --git a/src/main/java/org/kohsuke/github/GHMembership.java b/src/main/java/org/kohsuke/github/GHMembership.java new file mode 100644 index 0000000000..2847e1891c --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHMembership.java @@ -0,0 +1,84 @@ +package org.kohsuke.github; + +import java.io.IOException; +import java.net.URL; +import java.util.Locale; + +/** + * Represents a membership of a user in an organization. + * + * @author Kohsuke Kawaguchi + * @see GHMyself#listOrgMemberships() + */ +public class GHMembership /* extends GHObject --- but it doesn't have id, created_at, etc. */ { + GitHub root; + + String url; + String state; + String role; + GHUser user; + GHOrganization organization; + + public URL getUrl() { + return GitHub.parseURL(url); + } + + public State getState() { + return Enum.valueOf(State.class, state.toUpperCase(Locale.ENGLISH)); + } + + public Role getRole() { + return Enum.valueOf(Role.class, role.toUpperCase(Locale.ENGLISH)); + } + + public GHUser getUser() { + return user; + } + + public GHOrganization getOrganization() { + return organization; + } + + /** + * Accepts a pending invitation to an organization. + * + * @see GHMyself#getMembership(GHOrganization) + */ + public void activate() throws IOException { + root.retrieve().method("PATCH").with("state",State.ACTIVE).to(url,this); + } + + /*package*/ GHMembership wrap(GitHub root) { + this.root = root; + if (user!=null) user = root.getUser(user.wrapUp(root)); + if (organization!=null) organization.wrapUp(root); + return this; + } + + /*package*/ static void wrap(GHMembership[] page, GitHub root) { + for (GHMembership m : page) + m.wrap(root); + } + + /** + * Role of a user in an organization. + */ + public enum Role { + /** + * Organization owner. + */ + ADMIN, + /** + * Non-owner organization member. + */ + MEMBER; + } + + /** + * Whether a role is currently active or waiting for acceptance (pending) + */ + public enum State { + ACTIVE, + PENDING; + } +} diff --git a/src/main/java/org/kohsuke/github/GHMyself.java b/src/main/java/org/kohsuke/github/GHMyself.java index c7ae80dd79..cc05f03bc5 100644 --- a/src/main/java/org/kohsuke/github/GHMyself.java +++ b/src/main/java/org/kohsuke/github/GHMyself.java @@ -178,6 +178,39 @@ public PagedIterable listAllRepositories() { return listRepositories(); } + /** + * List your organization memberships + */ + public PagedIterable listOrgMemberships() { + return listOrgMemberships(null); + } + + /** + * List your organization memberships + * + * @param state + * Filter by a specific state + */ + public PagedIterable listOrgMemberships(final GHMembership.State state) { + return new PagedIterable() { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().with("state",state).asIterator("/user/memberships/orgs", GHMembership[].class, pageSize)) { + @Override + protected void wrapUp(GHMembership[] page) { + GHMembership.wrap(page,root); + } + }; + } + }; + } + + /** + * Gets your membership in a specific organization. + */ + public GHMembership getMembership(GHOrganization o) throws IOException { + return root.retrieve().to("/user/memberships/orgs/"+o.getLogin(),GHMembership.class).wrap(root); + } + // public void addEmails(Collection emails) throws IOException { //// new Requester(root,ApiVersion.V3).withCredential().to("/user/emails"); // root.retrieveWithAuth3() diff --git a/src/main/java/org/kohsuke/github/GHUser.java b/src/main/java/org/kohsuke/github/GHUser.java index 790f24ec20..77beb11b88 100644 --- a/src/main/java/org/kohsuke/github/GHUser.java +++ b/src/main/java/org/kohsuke/github/GHUser.java @@ -214,4 +214,9 @@ String getApiTailUrl(String tail) { if (tail.length()>0 && !tail.startsWith("/")) tail='/'+tail; return "/users/" + login + tail; } + + /*package*/ GHUser wrapUp(GitHub root) { + super.wrapUp(root); + return this; + } } diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 2a54626f2d..b50b2234ea 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -340,7 +340,7 @@ public void refreshCache() { /** * Interns the given {@link GHUser}. */ - protected GHUser getUser(GHUser orig) throws IOException { + protected GHUser getUser(GHUser orig) { GHUser u = users.get(orig.getLogin()); if (u==null) { orig.root = this; diff --git a/src/test/java/org/kohsuke/github/AppTest.java b/src/test/java/org/kohsuke/github/AppTest.java index 7246781127..0a958418be 100755 --- a/src/test/java/org/kohsuke/github/AppTest.java +++ b/src/test/java/org/kohsuke/github/AppTest.java @@ -888,6 +888,21 @@ public void reactions() throws Exception { a.delete(); } + @Test + public void listOrgMemberships() throws Exception { + GHMyself me = gitHub.getMyself(); + for (GHMembership m : me.listOrgMemberships()) { + assertThat(m.getUser(), is((GHUser)me)); + assertNotNull(m.getState()); + assertNotNull(m.getRole()); + + System.out.printf("%s %s %s\n", + m.getOrganization().getLogin(), + m.getState(), + m.getRole()); + } + } + private void kohsuke() { String login = getUser().getLogin(); Assume.assumeTrue(login.equals("kohsuke") || login.equals("kohsuke2")); From 0023ecefa4004180c86757042c96e92009022285 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Mon, 21 Nov 2016 08:53:38 -0800 Subject: [PATCH 199/390] [maven-release-plugin] prepare release github-api-1.81 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index cd302f7cd8..a2254c512d 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.81-SNAPSHOT + 1.81 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - HEAD + github-api-1.81 From a1df526f937efae5e6290e4b4a45d54e1a761131 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Mon, 21 Nov 2016 08:53:42 -0800 Subject: [PATCH 200/390] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index a2254c512d..df146ab5c9 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.81 + 1.82-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - github-api-1.81 + HEAD From 68ebc08c9d8bfdc48253f265c2c1484fd28e678b Mon Sep 17 00:00:00 2001 From: David Xia Date: Sat, 26 Nov 2016 00:44:52 -0500 Subject: [PATCH 201/390] Fix typos in javadocs Replace "pagenated" with "paginated". --- src/main/java/org/kohsuke/github/GHPerson.java | 4 ++-- src/main/java/org/kohsuke/github/PagedIterator.java | 2 +- src/main/java/org/kohsuke/github/Requester.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHPerson.java b/src/main/java/org/kohsuke/github/GHPerson.java index 67e157173f..f9872699ce 100644 --- a/src/main/java/org/kohsuke/github/GHPerson.java +++ b/src/main/java/org/kohsuke/github/GHPerson.java @@ -93,10 +93,10 @@ protected void wrapUp(GHRepository[] page) { } /** - * Loads repository list in a pagenated fashion. + * Loads repository list in a paginated fashion. * *

- * For a person with a lot of repositories, GitHub returns the list of repositories in a pagenated fashion. + * For a person with a lot of repositories, GitHub returns the list of repositories in a paginated fashion. * Unlike {@link #getRepositories()}, this method allows the caller to start processing data as it arrives. * * Every {@link Iterator#next()} call results in I/O. Exceptions that occur during the processing is wrapped diff --git a/src/main/java/org/kohsuke/github/PagedIterator.java b/src/main/java/org/kohsuke/github/PagedIterator.java index 9149290911..aaa8182076 100644 --- a/src/main/java/org/kohsuke/github/PagedIterator.java +++ b/src/main/java/org/kohsuke/github/PagedIterator.java @@ -6,7 +6,7 @@ import java.util.NoSuchElementException; /** - * Iterator over a pagenated data source. + * Iterator over a paginated data source. * * Aside from the normal iterator operation, this method exposes {@link #nextPage()} * that allows the caller to retrieve items per page. diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index 3d240abd65..70c48940c0 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -355,7 +355,7 @@ private boolean isMethodWithBody() { } /** - * Loads pagenated resources. + * Loads paginated resources. * * Every iterator call reports a new batch. */ From 0731f63237cc7c09c708db3b83089fa561e361a6 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 26 Nov 2016 14:45:03 -0800 Subject: [PATCH 202/390] Added order parameter --- src/main/java/org/kohsuke/github/GHIssueSearchBuilder.java | 5 +++++ .../java/org/kohsuke/github/GHRepositorySearchBuilder.java | 5 +++++ src/main/java/org/kohsuke/github/GHUserSearchBuilder.java | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHIssueSearchBuilder.java b/src/main/java/org/kohsuke/github/GHIssueSearchBuilder.java index ff574025c0..f9634a59f1 100644 --- a/src/main/java/org/kohsuke/github/GHIssueSearchBuilder.java +++ b/src/main/java/org/kohsuke/github/GHIssueSearchBuilder.java @@ -41,6 +41,11 @@ public GHIssueSearchBuilder isMerged() { return q("is:merged"); } + public GHIssueSearchBuilder order(GHDirection v) { + req.with("order",v); + return this; + } + public GHIssueSearchBuilder sort(Sort sort) { req.with("sort",sort); return this; diff --git a/src/main/java/org/kohsuke/github/GHRepositorySearchBuilder.java b/src/main/java/org/kohsuke/github/GHRepositorySearchBuilder.java index 8d30aaaf6b..03b12f5133 100644 --- a/src/main/java/org/kohsuke/github/GHRepositorySearchBuilder.java +++ b/src/main/java/org/kohsuke/github/GHRepositorySearchBuilder.java @@ -57,6 +57,11 @@ public GHRepositorySearchBuilder stars(String v) { return q("stars:"+v); } + public GHRepositorySearchBuilder order(GHDirection v) { + req.with("order",v); + return this; + } + public GHRepositorySearchBuilder sort(Sort sort) { req.with("sort",sort); return this; diff --git a/src/main/java/org/kohsuke/github/GHUserSearchBuilder.java b/src/main/java/org/kohsuke/github/GHUserSearchBuilder.java index fa5161683f..ca40f4d050 100644 --- a/src/main/java/org/kohsuke/github/GHUserSearchBuilder.java +++ b/src/main/java/org/kohsuke/github/GHUserSearchBuilder.java @@ -49,6 +49,11 @@ public GHUserSearchBuilder followers(String v) { return q("followers:"+v); } + public GHUserSearchBuilder order(GHDirection v) { + req.with("order",v); + return this; + } + public GHUserSearchBuilder sort(Sort sort) { req.with("sort",sort); return this; From 0780e10fa2eac368c5adf4f824c6bbdb3030c31d Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Tue, 13 Dec 2016 04:17:27 +0300 Subject: [PATCH 203/390] Added ghRepo.getBlob(String) method Signed-off-by: Kanstantsin Shautsou --- src/main/java/org/kohsuke/github/GHBlob.java | 30 +++++++++++++++++++ .../java/org/kohsuke/github/GHRepository.java | 8 +++++ .../java/org/kohsuke/github/GHTreeEntry.java | 4 +-- 3 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 src/main/java/org/kohsuke/github/GHBlob.java diff --git a/src/main/java/org/kohsuke/github/GHBlob.java b/src/main/java/org/kohsuke/github/GHBlob.java new file mode 100644 index 0000000000..f795da00d4 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHBlob.java @@ -0,0 +1,30 @@ +package org.kohsuke.github; + +/** + * @author Kanstantsin Shautsou + * @see Get a blob + */ +public class GHBlob { + private String content, encoding, url, sha; + private long size; + + public String getEncoding() { + return encoding; + } + + public String getUrl() { + return url; + } + + public String getSha() { + return sha; + } + + public long getSize() { + return size; + } + + public String getContent() { + return content; + } +} diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index f34ea85004..88346ea4cd 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -817,6 +817,14 @@ public GHTree getTreeRecursive(String sha, int recursive) throws IOException { return root.retrieve().to(url, GHTree.class).wrap(root); } + /** + * @see Get a blob + */ + public GHBlob getBlob(String blobSha) throws IOException { + String target = getApiTailUrl("git/blobs/" + blobSha); + return root.retrieve().to(target, GHBlob.class); + } + /** * Gets a commit object in this repository. */ diff --git a/src/main/java/org/kohsuke/github/GHTreeEntry.java b/src/main/java/org/kohsuke/github/GHTreeEntry.java index e3d831c073..8359c40cda 100644 --- a/src/main/java/org/kohsuke/github/GHTreeEntry.java +++ b/src/main/java/org/kohsuke/github/GHTreeEntry.java @@ -54,14 +54,14 @@ public String getType() { /** - * SHA1 of this object. + * SHA1 of this blob object. */ public String getSha() { return sha; } /** - * API URL to this Git data, such as + * API URL to this Git blob data, such as * https://api.github.com/repos/jenkinsci * /jenkins/git/commits/b72322675eb0114363a9a86e9ad5a170d1d07ac0 */ From c5009ab44b87a250d6272f51ad60d44c7b8474df Mon Sep 17 00:00:00 2001 From: Jesse Glick Date: Fri, 16 Dec 2016 15:04:10 -0500 Subject: [PATCH 204/390] Fix syntactically malformed test JSON. --- .../org/kohsuke/github/GHEventPayloadTest/label.json | 3 +-- .../org/kohsuke/github/GHEventPayloadTest/milestone.json | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/label.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/label.json index f85f636f89..b7a0be1b2e 100644 --- a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/label.json +++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/label.json @@ -65,8 +65,7 @@ "issues_url": "https://api.github.com/repos/baxterandthehackers/public-repo/issues{/number}", "pulls_url": "https://api.github.com/repos/baxterandthehackers/public-repo/pulls{/number}", "milestones_url": "https://api.github.com/repos/baxterandthehackers/public-repo/milestones{/number}", - "notifications_url": "https://api.github.com/repos/baxterandthehackers/public-repo/notifications{?since,all, - participating}", + "notifications_url": "https://api.github.com/repos/baxterandthehackers/public-repo/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/baxterandthehackers/public-repo/labels{/name}", "releases_url": "https://api.github.com/repos/baxterandthehackers/public-repo/releases{/id}", "deployments_url": "https://api.github.com/repos/baxterandthehackers/public-repo/deployments", diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/milestone.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/milestone.json index 7f262abd5c..1cd673eef5 100644 --- a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/milestone.json +++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/milestone.json @@ -2,8 +2,7 @@ "action": "created", "milestone": { "url": "https://api.github.com/repos/baxterandthehackers/public-repo/milestones/3", - "html_url": "https://github.com/baxterandthehackers/public-repo/milestones/Test%20milestone%20creation%20webhook - %20from%20command%20line2", + "html_url": "https://github.com/baxterandthehackers/public-repo/milestones/Test%20milestone%20creation%20webhook%20from%20command%20line2", "labels_url": "https://api.github.com/repos/baxterandthehackers/public-repo/milestones/3/labels", "id": 2055681, "number": 3, @@ -96,8 +95,7 @@ "issues_url": "https://api.github.com/repos/baxterandthehackers/public-repo/issues{/number}", "pulls_url": "https://api.github.com/repos/baxterandthehackers/public-repo/pulls{/number}", "milestones_url": "https://api.github.com/repos/baxterandthehackers/public-repo/milestones{/number}", - "notifications_url": "https://api.github.com/repos/baxterandthehackers/public-repo/notifications{?since,all, - participating}", + "notifications_url": "https://api.github.com/repos/baxterandthehackers/public-repo/notifications{?since,all,participating}", "labels_url": "https://api.github.com/repos/baxterandthehackers/public-repo/labels{/name}", "releases_url": "https://api.github.com/repos/baxterandthehackers/public-repo/releases{/id}", "deployments_url": "https://api.github.com/repos/baxterandthehackers/public-repo/deployments", From ccb42d32499ee1fcfe7dc9711f5e82eb5a9176b2 Mon Sep 17 00:00:00 2001 From: Jesse Glick Date: Fri, 16 Dec 2016 18:02:28 -0500 Subject: [PATCH 205/390] [JENKINS-36240] Added GHRepository.getPermission(String). --- .../java/org/kohsuke/github/GHPermission.java | 53 +++++++++++++++++++ .../java/org/kohsuke/github/GHRepository.java | 12 +++++ .../java/org/kohsuke/github/Requester.java | 11 ++-- .../org/kohsuke/github/RepositoryTest.java | 25 +++++++++ 4 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 src/main/java/org/kohsuke/github/GHPermission.java diff --git a/src/main/java/org/kohsuke/github/GHPermission.java b/src/main/java/org/kohsuke/github/GHPermission.java new file mode 100644 index 0000000000..8bc28c719a --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHPermission.java @@ -0,0 +1,53 @@ +/* + * The MIT License + * + * Copyright 2016 CloudBees, Inc. + * + * 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; + +/** + * Permission for a user in a repository. + * @see API + */ +public class GHPermission { + + private String permission; + private GHUser user; + + /** + * @return one of {@code admin}, {@code write}, {@code read}, or {@code none} + */ + public String getPermission() { + return permission; + } + + public GHUser getUser() { + return user; + } + + void wrapUp(GitHub root) { + if (user != null) { + user.root = root; + } + } + +} diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index f34ea85004..d3af91a210 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -480,6 +480,18 @@ public Set getCollaboratorNames() throws IOException { return r; } + /** + * Obtain permission for a given user in this repository. + * @param user a {@link GHUser#getLogin} + * @throws FileNotFoundException under some conditions (e.g., private repo you can see but are not an admin of); treat as unknown + * @throws HttpException with a 403 under other conditions (e.g., public repo you have no special rights to); treat as unknown + */ + public GHPermission getPermission(String user) throws IOException { + GHPermission perm = root.retrieve().withHeader("Accept", "application/vnd.github.korra-preview").to(getApiTailUrl("collaborators/" + user + "/permission"), GHPermission.class); + perm.wrapUp(root); + return perm; + } + /** * If this repository belongs to an organization, return a set of teams. */ diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index 70c48940c0..2eb3f282fb 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -598,11 +598,16 @@ private InputStream wrapStream(InputStream in) throws IOException { InputStream es = wrapStream(uc.getErrorStream()); try { if (es!=null) { + String error = IOUtils.toString(es, "UTF-8"); if (e instanceof FileNotFoundException) { // pass through 404 Not Found to allow the caller to handle it intelligently - throw (IOException) new FileNotFoundException(IOUtils.toString(es, "UTF-8")).initCause(e); - } else - throw (IOException) new IOException(IOUtils.toString(es, "UTF-8")).initCause(e); + throw (IOException) new FileNotFoundException(error).initCause(e); + } else if (e instanceof HttpException) { + HttpException http = (HttpException) e; + throw (IOException) new HttpException(error, http.getResponseCode(), http.getResponseMessage(), http.getUrl(), e); + } else { + throw (IOException) new IOException(error).initCause(e); + } } else throw e; } finally { diff --git a/src/test/java/org/kohsuke/github/RepositoryTest.java b/src/test/java/org/kohsuke/github/RepositoryTest.java index dae2892a45..21625fbf89 100644 --- a/src/test/java/org/kohsuke/github/RepositoryTest.java +++ b/src/test/java/org/kohsuke/github/RepositoryTest.java @@ -1,9 +1,11 @@ package org.kohsuke.github; +import java.io.FileNotFoundException; import org.junit.Test; import org.kohsuke.github.GHRepository.Contributor; import java.io.IOException; +import org.junit.Ignore; /** * @author Kohsuke Kawaguchi @@ -40,6 +42,29 @@ public void listContributors() throws IOException { assertTrue(kohsuke); } + @Ignore("depends on who runs this test whether it can pass or not") + @Test + public void getPermission() throws Exception { + GHRepository r = gitHub.getOrganization("cloudbeers").getRepository("yolo"); + assertEquals("admin", r.getPermission("jglick").getPermission()); + assertEquals("read", r.getPermission("dude").getPermission()); + r = gitHub.getOrganization("cloudbees").getRepository("private-repo-not-writable-by-me"); + try { + r.getPermission("jglick"); + fail(); + } catch (FileNotFoundException x) { + x.printStackTrace(); // good + } + r = gitHub.getOrganization("apache").getRepository("groovy"); + try { + r.getPermission("jglick"); + fail(); + } catch (HttpException x) { + x.printStackTrace(); // good + assertEquals(403, x.getResponseCode()); + } + } + private GHRepository getRepository() throws IOException { return gitHub.getOrganization("github-api-test-org").getRepository("jenkins"); } From 6380cf9ed0551ecaf6dbec27262f7ce79e2e33c9 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 17 Dec 2016 06:46:33 -0800 Subject: [PATCH 206/390] Added a method to retrieve the actual bytes of BLOB ... which is probably more useful than the getContent() method --- src/main/java/org/kohsuke/github/GHBlob.java | 45 +++++++++++++++++--- 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHBlob.java b/src/main/java/org/kohsuke/github/GHBlob.java index f795da00d4..7327fbfb13 100644 --- a/src/main/java/org/kohsuke/github/GHBlob.java +++ b/src/main/java/org/kohsuke/github/GHBlob.java @@ -1,30 +1,63 @@ package org.kohsuke.github; +import org.apache.commons.codec.binary.Base64InputStream; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URL; + /** * @author Kanstantsin Shautsou + * @author Kohsuke Kawaguchi + * @see GHRepository#getBlob(String) * @see Get a blob */ public class GHBlob { private String content, encoding, url, sha; private long size; - public String getEncoding() { - return encoding; - } - - public String getUrl() { - return url; + /** + * API URL of this blob. + */ + public URL getUrl() { + return GitHub.parseURL(url); } public String getSha() { return sha; } + /** + * Number of bytes in this blob. + */ public long getSize() { return size; } + public String getEncoding() { + return encoding; + } + + /** + * Encoded content. You probably want {@link #read()} + */ public String getContent() { return content; } + + /** + * Retrieves the actual bytes of the blob. + */ + public InputStream read() { + if (encoding.equals("base64")) { + try { + return new Base64InputStream(new ByteArrayInputStream(content.getBytes("US-ASCII")), false); + } catch (UnsupportedEncodingException e) { + throw new AssertionError(e); // US-ASCII is mandatory + } + } + + throw new UnsupportedOperationException("Unrecognized encoding: "+encoding); + } } From e6ee278fdef1d498deee8cd30bf1fd62eed52898 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 17 Dec 2016 06:55:44 -0800 Subject: [PATCH 207/390] Another version that directly reads BLOB without going through an intermediate object. --- .../java/org/kohsuke/github/GHRepository.java | 18 ++++++++++++++++ src/test/java/org/kohsuke/github/AppTest.java | 21 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 88346ea4cd..ac0d57b5fc 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -31,6 +31,7 @@ import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; import java.io.InterruptedIOException; import java.io.Reader; @@ -818,13 +819,30 @@ public GHTree getTreeRecursive(String sha, int recursive) throws IOException { } /** + * Obtains the metadata & the content of a blob. + * + *

+ * This method retrieves the whole content in memory, so beware when you are dealing with large BLOB. + * * @see Get a blob + * @see #readBlob(String) */ public GHBlob getBlob(String blobSha) throws IOException { String target = getApiTailUrl("git/blobs/" + blobSha); return root.retrieve().to(target, GHBlob.class); } + /** + * Reads the content of a blob as a stream for better efficiency. + * + * @see Get a blob + * @see #getBlob(String) + */ + public InputStream readBlob(String blobSha) throws IOException { + String target = getApiTailUrl("git/blobs/" + blobSha); + return root.retrieve().withHeader("Accept","application/vnd.github.VERSION.raw").asStream(target); + } + /** * Gets a commit object in this repository. */ diff --git a/src/test/java/org/kohsuke/github/AppTest.java b/src/test/java/org/kohsuke/github/AppTest.java index 0a958418be..157d105408 100755 --- a/src/test/java/org/kohsuke/github/AppTest.java +++ b/src/test/java/org/kohsuke/github/AppTest.java @@ -12,6 +12,7 @@ import org.kohsuke.github.GHOrganization.Permission; import java.io.IOException; +import java.io.InputStream; import java.net.URL; import java.util.*; import java.util.Map.Entry; @@ -903,6 +904,26 @@ public void listOrgMemberships() throws Exception { } } + @Test + public void blob() throws Exception { + GHRepository r = gitHub.getRepository("kohsuke/github-api"); + String sha1 = "a12243f2fc5b8c2ba47dd677d0b0c7583539584d"; + + assertBlobContent(r.readBlob(sha1)); + + GHBlob blob = r.getBlob(sha1); + assertBlobContent(blob.read()); + assertThat(blob.getSha(),is("a12243f2fc5b8c2ba47dd677d0b0c7583539584d")); + assertThat(blob.getSize(),is(1104L)); + } + + private void assertBlobContent(InputStream is) throws Exception { + String content = new String(IOUtils.toByteArray(is),"UTF-8"); + assertThat(content,containsString("Copyright (c) 2011- Kohsuke Kawaguchi and other contributors")); + assertThat(content,containsString("FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR")); + assertThat(content.length(),is(1104)); + } + private void kohsuke() { String login = getUser().getLogin(); Assume.assumeTrue(login.equals("kohsuke") || login.equals("kohsuke2")); From 88d52c44ad51c22dd32ec9f40651d3ef4f6f6422 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 17 Dec 2016 07:03:40 -0800 Subject: [PATCH 208/390] Recording parent GHRepository --- src/main/java/org/kohsuke/github/GHRepository.java | 4 ++-- src/main/java/org/kohsuke/github/GHTree.java | 9 ++++++--- src/main/java/org/kohsuke/github/GHTreeEntry.java | 2 ++ 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index ac0d57b5fc..3442e37d32 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -800,7 +800,7 @@ public GHRef getRef(String refName) throws IOException { */ public GHTree getTree(String sha) throws IOException { String url = String.format("/repos/%s/%s/git/trees/%s", getOwnerName(), name, sha); - return root.retrieve().to(url, GHTree.class).wrap(root); + return root.retrieve().to(url, GHTree.class).wrap(this); } /** @@ -815,7 +815,7 @@ public GHTree getTree(String sha) throws IOException { */ public GHTree getTreeRecursive(String sha, int recursive) throws IOException { String url = String.format("/repos/%s/%s/git/trees/%s?recursive=%d", getOwnerName(), name, sha, recursive); - return root.retrieve().to(url, GHTree.class).wrap(root); + return root.retrieve().to(url, GHTree.class).wrap(this); } /** diff --git a/src/main/java/org/kohsuke/github/GHTree.java b/src/main/java/org/kohsuke/github/GHTree.java index aaf98e77e2..38b53cd4a1 100644 --- a/src/main/java/org/kohsuke/github/GHTree.java +++ b/src/main/java/org/kohsuke/github/GHTree.java @@ -13,7 +13,7 @@ * @see GHRepository#getTree(String) */ public class GHTree { - /* package almost final */GitHub root; + /* package almost final */GHRepository repo; private boolean truncated; private String sha, url; @@ -50,8 +50,11 @@ public URL getUrl() { return GitHub.parseURL(url); } - /* package */GHTree wrap(GitHub root) { - this.root = root; + /* package */GHTree wrap(GHRepository repo) { + this.repo = repo; + for (GHTreeEntry e : tree) { + e.tree = this; + } return this; } diff --git a/src/main/java/org/kohsuke/github/GHTreeEntry.java b/src/main/java/org/kohsuke/github/GHTreeEntry.java index 8359c40cda..3c069853c0 100644 --- a/src/main/java/org/kohsuke/github/GHTreeEntry.java +++ b/src/main/java/org/kohsuke/github/GHTreeEntry.java @@ -10,6 +10,8 @@ * @see GHTree */ public class GHTreeEntry { + /* package almost final */GHTree tree; + private String path, mode, type, sha, url; private long size; From 11651da411006f3fdbfa824d197566dc4f87a19f Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 17 Dec 2016 07:04:14 -0800 Subject: [PATCH 209/390] not always a blob, for example it could be a tree. --- src/main/java/org/kohsuke/github/GHTreeEntry.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHTreeEntry.java b/src/main/java/org/kohsuke/github/GHTreeEntry.java index 3c069853c0..e368bb6680 100644 --- a/src/main/java/org/kohsuke/github/GHTreeEntry.java +++ b/src/main/java/org/kohsuke/github/GHTreeEntry.java @@ -46,7 +46,7 @@ public long getSize() { /** * Gets the type such as: - * "blob" + * "blob", "tree", etc. * * @return The type */ @@ -56,14 +56,14 @@ public String getType() { /** - * SHA1 of this blob object. + * SHA1 of this object. */ public String getSha() { return sha; } /** - * API URL to this Git blob data, such as + * API URL to this Git data, such as * https://api.github.com/repos/jenkinsci * /jenkins/git/commits/b72322675eb0114363a9a86e9ad5a170d1d07ac0 */ From b5386a35ee59c223ab2b692e87d6120c3761e59c Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 17 Dec 2016 07:09:29 -0800 Subject: [PATCH 210/390] Defining better traversal methods for apps that walk trees --- src/main/java/org/kohsuke/github/GHBlob.java | 1 + src/main/java/org/kohsuke/github/GHTree.java | 1 + .../java/org/kohsuke/github/GHTreeEntry.java | 35 +++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHBlob.java b/src/main/java/org/kohsuke/github/GHBlob.java index 7327fbfb13..a38a18219c 100644 --- a/src/main/java/org/kohsuke/github/GHBlob.java +++ b/src/main/java/org/kohsuke/github/GHBlob.java @@ -10,6 +10,7 @@ /** * @author Kanstantsin Shautsou * @author Kohsuke Kawaguchi + * @see GHTreeEntry#asBlob() * @see GHRepository#getBlob(String) * @see Get a blob */ diff --git a/src/main/java/org/kohsuke/github/GHTree.java b/src/main/java/org/kohsuke/github/GHTree.java index 38b53cd4a1..de60611253 100644 --- a/src/main/java/org/kohsuke/github/GHTree.java +++ b/src/main/java/org/kohsuke/github/GHTree.java @@ -11,6 +11,7 @@ * * @author Daniel Teixeira - https://github.com/ddtxra * @see GHRepository#getTree(String) + * @see GHTreeEntry#asTree() */ public class GHTree { /* package almost final */GHRepository repo; diff --git a/src/main/java/org/kohsuke/github/GHTreeEntry.java b/src/main/java/org/kohsuke/github/GHTreeEntry.java index e368bb6680..ba6d45e15e 100644 --- a/src/main/java/org/kohsuke/github/GHTreeEntry.java +++ b/src/main/java/org/kohsuke/github/GHTreeEntry.java @@ -1,5 +1,7 @@ package org.kohsuke.github; +import java.io.IOException; +import java.io.InputStream; import java.net.URL; /** @@ -70,4 +72,37 @@ public String getSha() { public URL getUrl() { return GitHub.parseURL(url); } + + /** + * If this tree entry represents a file, then return its information. + * Otherwise null. + */ + public GHBlob asBlob() throws IOException { + if (type.equals("blob")) + return tree.repo.getBlob(sha); + else + return null; + } + + /** + * If this tree entry represents a file, then return its content. + * Otherwise null. + */ + public InputStream readAsBlob() throws IOException { + if (type.equals("blob")) + return tree.repo.readBlob(sha); + else + return null; + } + + /** + * If this tree entry represents a directory, then return it. + * Otherwise null. + */ + public GHTree asTree() throws IOException { + if (type.equals("tree")) + return tree.repo.getTree(sha); + else + return null; + } } From a454fb10ec6fb562329dcaf192708e2e85a8bfdb Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 17 Dec 2016 07:21:31 -0800 Subject: [PATCH 211/390] Tree traversal from commit & its associated tests --- src/main/java/org/kohsuke/github/GHCommit.java | 13 +++++++++++++ src/main/java/org/kohsuke/github/GHTree.java | 14 ++++++++++++++ src/test/java/org/kohsuke/github/AppTest.java | 5 +++++ 3 files changed, 32 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHCommit.java b/src/main/java/org/kohsuke/github/GHCommit.java index 3740778480..ec5dfbffc1 100644 --- a/src/main/java/org/kohsuke/github/GHCommit.java +++ b/src/main/java/org/kohsuke/github/GHCommit.java @@ -37,6 +37,12 @@ public static class ShortInfo { private int comment_count; + static class Tree { + String sha; + } + + private Tree tree; + @WithBridgeMethods(value = GHAuthor.class, castRequired = true) public GitUser getAuthor() { return author; @@ -224,6 +230,13 @@ public int getLinesDeleted() throws IOException { return stats.deletions; } + /** + * Use this method to walk the tree + */ + public GHTree getTree() throws IOException { + return owner.getTree(getCommitShortInfo().tree.sha); + } + /** * URL of this commit like "https://github.com/kohsuke/sandbox-ant/commit/8ae38db0ea5837313ab5f39d43a6f73de3bd9000" */ diff --git a/src/main/java/org/kohsuke/github/GHTree.java b/src/main/java/org/kohsuke/github/GHTree.java index de60611253..59c7cd287e 100644 --- a/src/main/java/org/kohsuke/github/GHTree.java +++ b/src/main/java/org/kohsuke/github/GHTree.java @@ -10,6 +10,7 @@ * https://developer.github.com/v3/git/trees/ * * @author Daniel Teixeira - https://github.com/ddtxra + * @see GHCommit#getTree() * @see GHRepository#getTree(String) * @see GHTreeEntry#asTree() */ @@ -35,6 +36,19 @@ public List getTree() { return Collections.unmodifiableList(Arrays.asList(tree)); } + /** + * Finds a tree entry by its name. + * + * IOW, find a directory entry by a file name. + */ + public GHTreeEntry getEntry(String path) { + for (GHTreeEntry e : tree) { + if (e.getPath().equals(path)) + return e; + } + return null; + } + /** * 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. diff --git a/src/test/java/org/kohsuke/github/AppTest.java b/src/test/java/org/kohsuke/github/AppTest.java index 157d105408..e1d513d739 100755 --- a/src/test/java/org/kohsuke/github/AppTest.java +++ b/src/test/java/org/kohsuke/github/AppTest.java @@ -363,6 +363,11 @@ public void testCommit() throws Exception { assertEquals(48,f.getLinesChanged()); assertEquals("modified",f.getStatus()); assertEquals("changelog.html", f.getFileName()); + + // walk the tree + GHTree t = commit.getTree(); + assertThat(IOUtils.toString(t.getEntry("todo.txt").readAsBlob()), containsString("executor rendering")); + assertNotNull(t.getEntry("war").asTree()); } @Test From 3a66e90b7aadbd43c70a2ae391c39af037ae0415 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 17 Dec 2016 07:28:28 -0800 Subject: [PATCH 212/390] Fixed issue #319 getApiUrl() is unreliable given that we collapse issue & PR into one object. --- src/main/java/org/kohsuke/github/GHPullRequest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index a6becf495c..04898039bc 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -213,7 +213,7 @@ private void populate() throws IOException { public PagedIterable listFiles() { return new PagedIterable() { public PagedIterator _iterator(int pageSize) { - return new PagedIterator(root.retrieve().asIterator(String.format("%s/files", getApiURL()), + return new PagedIterator(root.retrieve().asIterator(String.format("%s/files", getApiRoute()), GHPullRequestFileDetail[].class, pageSize)) { @Override protected void wrapUp(GHPullRequestFileDetail[] page) { @@ -247,7 +247,7 @@ public PagedIterable listCommits() { return new PagedIterable() { public PagedIterator _iterator(int pageSize) { return new PagedIterator(root.retrieve().asIterator( - String.format("%s/commits", getApiURL()), + String.format("%s/commits", getApiRoute()), GHPullRequestCommitDetail[].class, pageSize)) { @Override protected void wrapUp(GHPullRequestCommitDetail[] page) { From 32177283b3e4f321a5ae26e5175def5936a3440d Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 17 Dec 2016 07:30:14 -0800 Subject: [PATCH 213/390] Fixed issue #317 There's no need for the library to replicate a logic when GitHub does that (and does that correctly.) Looking at the commit history, I couldn't see why this was added in the first place. --- src/main/java/org/kohsuke/github/GHRepository.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 3442e37d32..4a0d410621 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -505,7 +505,6 @@ public void removeCollaborators(Collection users) throws IOException { } private void modifyCollaborators(Collection users, String method) throws IOException { - verifyMine(); for (GHUser user : users) { new Requester(root).method(method).to(getApiTailUrl("collaborators/" + user.getLogin())); } @@ -1118,11 +1117,6 @@ public GHHook createWebHook(URL url) throws IOException { // return root.retrieveWithAuth("/pulls/"+owner+'/'+name,JsonPullRequests.class).wrap(root); // } - private void verifyMine() throws IOException { - if (!root.login.equals(getOwnerName())) - throw new IOException("Operation not applicable to a repository owned by someone else: " + getOwnerName()); - } - /** * Returns a set that represents the post-commit hook URLs. * The returned set is live, and changes made to them are reflected to GitHub. From 3dbb516084f0d1e2c02c83d20e1ed1d2ce0b6c5c Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 17 Dec 2016 07:50:48 -0800 Subject: [PATCH 214/390] [maven-release-plugin] prepare release github-api-1.82 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index df146ab5c9..bd00bca40c 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.82-SNAPSHOT + 1.82 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - HEAD + github-api-1.82 From a746a310bcac5ffbd9670010b24eb83b9257fb07 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 17 Dec 2016 07:50:55 -0800 Subject: [PATCH 215/390] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index bd00bca40c..449ac7877f 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.82 + 1.83-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - github-api-1.82 + HEAD From 470da06ecf3d4f36995c440103eb8c17ac799f3b Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 17 Dec 2016 08:17:20 -0800 Subject: [PATCH 216/390] Cleaning up javadoc warnings --- pom.xml | 2 +- src/main/java/org/kohsuke/github/GHRelease.java | 4 +--- src/main/java/org/kohsuke/github/GHReleaseBuilder.java | 1 - src/main/java/org/kohsuke/github/GHRepository.java | 3 +-- src/main/java/org/kohsuke/github/GHTree.java | 1 - src/main/java/org/kohsuke/github/GitHub.java | 1 - 6 files changed, 3 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index 449ac7877f..40bf81cbf2 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.kohsuke pom - 14 + 17 github-api diff --git a/src/main/java/org/kohsuke/github/GHRelease.java b/src/main/java/org/kohsuke/github/GHRelease.java index b61dc62b38..96421da415 100644 --- a/src/main/java/org/kohsuke/github/GHRelease.java +++ b/src/main/java/org/kohsuke/github/GHRelease.java @@ -121,9 +121,7 @@ static GHRelease[] wrap(GHRelease[] releases, GHRepository owner) { * Java 7 or greater. Options for fixing this for earlier JVMs can be found here * http://stackoverflow.com/questions/12361090/server-name-indication-sni-on-java but involve more complicated * handling of the HTTP requests to github's API. - * - * @throws IOException - */ + */ public GHAsset uploadAsset(File file, String contentType) throws IOException { Requester builder = new Requester(owner.root); diff --git a/src/main/java/org/kohsuke/github/GHReleaseBuilder.java b/src/main/java/org/kohsuke/github/GHReleaseBuilder.java index 04e368f2b2..b1daac956e 100644 --- a/src/main/java/org/kohsuke/github/GHReleaseBuilder.java +++ b/src/main/java/org/kohsuke/github/GHReleaseBuilder.java @@ -33,7 +33,6 @@ public GHReleaseBuilder body(String body) { * * @param commitish Defaults to the repository’s default branch (usually "master"). Unused if the Git tag * already exists. - * @return */ public GHReleaseBuilder commitish(String commitish) { if (commitish != null) { diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 4a0d410621..73bcd99d19 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -449,7 +449,6 @@ public GHPersonSet getCollaborators() throws IOException { * Lists up the collaborators on this repository. * * @return Users - * @throws IOException */ public PagedIterable listCollaborators() throws IOException { return listUsers("collaborators"); @@ -818,7 +817,7 @@ public GHTree getTreeRecursive(String sha, int recursive) throws IOException { } /** - * Obtains the metadata & the content of a blob. + * Obtains the metadata & the content of a blob. * *

* This method retrieves the whole content in memory, so beware when you are dealing with large BLOB. diff --git a/src/main/java/org/kohsuke/github/GHTree.java b/src/main/java/org/kohsuke/github/GHTree.java index 59c7cd287e..d52e02a793 100644 --- a/src/main/java/org/kohsuke/github/GHTree.java +++ b/src/main/java/org/kohsuke/github/GHTree.java @@ -30,7 +30,6 @@ public String getSha() { /** * Return an array of entries of the trees - * @return */ public List getTree() { return Collections.unmodifiableList(Arrays.asList(tree)); diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index b50b2234ea..5d613fe985 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -416,7 +416,6 @@ protected void wrapUp(GHUser[] page) { * * @param key The license key provided from the API * @return The license details - * @throws IOException * @see GHLicense#getKey() */ @Preview @Deprecated From 26c20a7a224a066bb06b71461143ec517669dd61 Mon Sep 17 00:00:00 2001 From: "Jeffrey.Nelson" Date: Thu, 22 Dec 2016 11:55:01 -0600 Subject: [PATCH 217/390] add branch protection attributes --- .../java/org/kohsuke/github/GHBranch.java | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHBranch.java b/src/main/java/org/kohsuke/github/GHBranch.java index 4c80db9ef4..9870732d0d 100644 --- a/src/main/java/org/kohsuke/github/GHBranch.java +++ b/src/main/java/org/kohsuke/github/GHBranch.java @@ -1,13 +1,16 @@ package org.kohsuke.github; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import org.kohsuke.github.BranchProtection.RequiredStatusChecks; +import static org.kohsuke.github.Previews.LOKI; import java.io.IOException; import java.util.Arrays; import java.util.Collection; -import static org.kohsuke.github.Previews.LOKI; +import org.kohsuke.github.BranchProtection.RequiredStatusChecks; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; /** * A branch in a repository. @@ -22,6 +25,10 @@ public class GHBranch { private String name; private Commit commit; + @JsonProperty("protected") + private boolean protection; + private String protection_url; + public static class Commit { String sha; @@ -44,6 +51,15 @@ public GHRepository getOwner() { public String getName() { return name; } + + public boolean isProtected() { + return protection; + } + + public String getProtection_url() { + return protection_url; + } + /** * The commit that this branch currently points to. From 9d03435aa14703c1a573371919e4151ad84a0848 Mon Sep 17 00:00:00 2001 From: Stephen Connolly Date: Thu, 5 Jan 2017 09:21:32 +0000 Subject: [PATCH 218/390] Expose Rate Limit Headers Exposes the rate limit header responses so that consumers of the API can proactively tune their usage --- src/main/java/org/kohsuke/github/GitHub.java | 27 +++++++ .../java/org/kohsuke/github/Requester.java | 76 +++++++++++++++++-- 2 files changed, 96 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 5d613fe985..fc258e8a02 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -50,6 +50,8 @@ import java.util.Set; import java.util.TimeZone; +import java.util.logging.Level; +import javax.annotation.CheckForNull; import org.apache.commons.codec.Charsets; import org.apache.commons.codec.binary.Base64; @@ -90,6 +92,9 @@ public class GitHub { private HttpConnector connector = HttpConnector.DEFAULT; + private final Object headerRateLimitLock = new Object(); + private GHRateLimit headerRateLimit = null; + /** * Creates a client API root object. * @@ -300,6 +305,28 @@ public GHRateLimit getRateLimit() throws IOException { } } + /*package*/ void updateRateLimit(@Nonnull GHRateLimit observed) { + synchronized (headerRateLimitLock) { + if (headerRateLimit == null + || headerRateLimit.getResetDate().getTime() < observed.getResetDate().getTime() + || headerRateLimit.remaining > observed.remaining) { + headerRateLimit = observed; + LOGGER.log(Level.INFO, "Rate limit now: {0}", headerRateLimit); + } + } + } + + /** + * Returns the most recently observed rate limit data or {@code null} if either there is no rate limit + * (for example GitHub Enterprise) or if no requests have been made. + * + * @return the most recentlt observed rate limit data or {@code null}. + */ + @CheckForNull + public GHRateLimit lastRateLimit() { + return headerRateLimit; + } + /** * Gets the {@link GHUser} that represents yourself. */ diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index 70c48940c0..21b3afd150 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -25,8 +25,6 @@ import com.fasterxml.jackson.databind.JsonMappingException; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import org.apache.commons.io.IOUtils; - import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; @@ -42,6 +40,7 @@ import java.net.URLEncoder; import java.util.ArrayList; import java.util.Collection; +import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; @@ -49,16 +48,18 @@ import java.util.Locale; import java.util.Map; import java.util.NoSuchElementException; +import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.GZIPInputStream; - import javax.annotation.WillClose; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringUtils; import static java.util.Arrays.asList; import static java.util.logging.Level.FINE; -import static org.kohsuke.github.GitHub.*; +import static org.kohsuke.github.GitHub.MAPPER; /** * A builder pattern for making HTTP call and parsing its output. @@ -281,6 +282,8 @@ private T _to(String tailApiUrl, Class type, T instance) throws IOExcepti return result; } catch (IOException e) { handleApiError(e); + } finally { + noteRateLimit(tailApiUrl); } } } @@ -299,6 +302,8 @@ public int asHttpStatusCode(String tailApiUrl) throws IOException { return uc.getResponseCode(); } catch (IOException e) { handleApiError(e); + } finally { + noteRateLimit(tailApiUrl); } } } @@ -313,6 +318,59 @@ public InputStream asStream(String tailApiUrl) throws IOException { return wrapStream(uc.getInputStream()); } catch (IOException e) { handleApiError(e); + } finally { + noteRateLimit(tailApiUrl); + } + } + } + + private void noteRateLimit(String tailApiUrl) { + if ("/rate_limit".equals(tailApiUrl)) { + // the rate_limit API is "free" + return; + } + if (tailApiUrl.startsWith("/search")) { + // the search API uses a different rate limit + return; + } + String limit = uc.getHeaderField("X-RateLimit-Limit"); + if (StringUtils.isBlank(limit)) { + // if we are missing a header, return fast + return; + } + String remaining = uc.getHeaderField("X-RateLimit-Remaining"); + if (StringUtils.isBlank(remaining)) { + // if we are missing a header, return fast + return; + } + String reset = uc.getHeaderField("X-RateLimit-Reset"); + if (StringUtils.isBlank(reset)) { + // if we are missing a header, return fast + return; + } + GHRateLimit observed = new GHRateLimit(); + try { + observed.limit = Integer.parseInt(limit); + } catch (NumberFormatException e) { + if (LOGGER.isLoggable(Level.FINEST)) { + LOGGER.log(Level.FINEST, "Malformed X-RateLimit-Limit header value " + limit, e); + } + return; + } + try { + observed.remaining = Integer.parseInt(remaining); + } catch (NumberFormatException e) { + if (LOGGER.isLoggable(Level.FINEST)) { + LOGGER.log(Level.FINEST, "Malformed X-RateLimit-Remaining header value " + remaining, e); + } + return; + } + try { + observed.reset = new Date(Long.parseLong(reset)); // this is madness, storing the date as seconds + root.updateRateLimit(observed); + } catch (NumberFormatException e) { + if (LOGGER.isLoggable(Level.FINEST)) { + LOGGER.log(Level.FINEST, "Malformed X-RateLimit-Reset header value " + reset, e); } } } @@ -382,7 +440,7 @@ private boolean isMethodWithBody() { } try { - return new PagingIterator(type, root.getApiURL(s.toString())); + return new PagingIterator(type, tailApiUrl, root.getApiURL(s.toString())); } catch (IOException e) { throw new Error(e); } @@ -391,6 +449,7 @@ private boolean isMethodWithBody() { class PagingIterator implements Iterator { private final Class type; + private final String tailApiUrl; /** * The next batch to be returned from {@link #next()}. @@ -402,9 +461,10 @@ class PagingIterator implements Iterator { */ private URL url; - PagingIterator(Class type, URL url) { - this.url = url; + PagingIterator(Class type, String tailApiUrl, URL url) { this.type = type; + this.tailApiUrl = tailApiUrl; + this.url = url; } public boolean hasNext() { @@ -438,6 +498,8 @@ private void fetch() { return; } catch (IOException e) { handleApiError(e); + } finally { + noteRateLimit(tailApiUrl); } } } catch (IOException e) { From dfea424b9412f4162ea8b94114c15f92897f5baf Mon Sep 17 00:00:00 2001 From: Stephen Connolly Date: Thu, 5 Jan 2017 09:36:58 +0000 Subject: [PATCH 219/390] Expose the API url used by the GitHub --- 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 fc258e8a02..4d9d04c089 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -259,6 +259,10 @@ public HttpConnector getConnector() { return connector; } + public String getApiUrl() { + return apiUrl; + } + /** * Sets the custom connector used to make requests to GitHub. */ From 6fcddf4a475e5b59b8e7644d44e857126635a056 Mon Sep 17 00:00:00 2001 From: Stephen Connolly Date: Thu, 5 Jan 2017 10:24:16 +0000 Subject: [PATCH 220/390] Some usage patterns require more pro-active rate limit queries --- src/main/java/org/kohsuke/github/GitHub.java | 61 +++++++++++++------- 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 4d9d04c089..df9353e032 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -23,12 +23,10 @@ */ package org.kohsuke.github; -import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.ANY; -import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE; -import static java.util.logging.Level.FINE; -import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; -import static org.kohsuke.github.Previews.DRAX; - +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.io.ByteArrayInputStream; import java.io.FileNotFoundException; import java.io.IOException; @@ -49,19 +47,19 @@ import java.util.Map; import java.util.Set; import java.util.TimeZone; - +import java.util.concurrent.TimeUnit; import java.util.logging.Level; +import java.util.logging.Logger; import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; import org.apache.commons.codec.Charsets; import org.apache.commons.codec.binary.Base64; -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 javax.annotation.Nonnull; -import java.util.logging.Logger; +import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.ANY; +import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE; +import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; +import static java.util.logging.Level.FINE; +import static org.kohsuke.github.Previews.DRAX; /** * Root of the GitHub API. @@ -94,6 +92,7 @@ public class GitHub { private final Object headerRateLimitLock = new Object(); private GHRateLimit headerRateLimit = null; + private volatile GHRateLimit rateLimit = null; /** * Creates a client API root object. @@ -296,16 +295,16 @@ public void setConnector(HttpConnector connector) { */ public GHRateLimit getRateLimit() throws IOException { try { - return retrieve().to("/rate_limit", JsonRateLimit.class).rate; + return rateLimit = retrieve().to("/rate_limit", JsonRateLimit.class).rate; } catch (FileNotFoundException e) { // GitHub Enterprise doesn't have the rate limit, so in that case // return some big number that's not too big. // see issue #78 GHRateLimit r = new GHRateLimit(); r.limit = r.remaining = 1000000; - long hours = 1000L * 60 * 60; - r.reset = new Date(System.currentTimeMillis() + 1 * hours ); - return r; + long hour = 60L * 60L; // this is madness, storing the date as seconds in a Date object + r.reset = new Date((System.currentTimeMillis() + hour) / 1000L ); + return rateLimit = r; } } @@ -324,11 +323,33 @@ public GHRateLimit getRateLimit() throws IOException { * Returns the most recently observed rate limit data or {@code null} if either there is no rate limit * (for example GitHub Enterprise) or if no requests have been made. * - * @return the most recentlt observed rate limit data or {@code null}. + * @return the most recently observed rate limit data or {@code null}. */ @CheckForNull public GHRateLimit lastRateLimit() { - return headerRateLimit; + synchronized (headerRateLimitLock) { + return headerRateLimit; + } + } + + /** + * Gets the current rate limit while trying not to actually make any remote requests unless absolutely necessary. + * + * @return the current rate limit data. + * @throws IOException if we couldn't get the current rate limit data. + */ + @Nonnull + public GHRateLimit rateLimit() throws IOException { + synchronized (headerRateLimitLock) { + if (headerRateLimit != null) { + return headerRateLimit; + } + } + GHRateLimit rateLimit = this.rateLimit; + if (rateLimit == null || rateLimit.getResetDate().getTime() < System.currentTimeMillis()) { + rateLimit = getRateLimit(); + } + return rateLimit; } /** From 1212ae3eb3f854ea903675ffe6535af6982d5808 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Mon, 9 Jan 2017 16:06:05 -0800 Subject: [PATCH 221/390] Touch up for uniformity - Prefer typed 'URL' over 'String' that is URL - Mark API as @Preview to communicate that this is subject to change More branch protection stuff needs to be added. See https://developer.github.com/v3/repos/branches/ --- src/main/java/org/kohsuke/github/GHBranch.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHBranch.java b/src/main/java/org/kohsuke/github/GHBranch.java index 9870732d0d..f54bea9f47 100644 --- a/src/main/java/org/kohsuke/github/GHBranch.java +++ b/src/main/java/org/kohsuke/github/GHBranch.java @@ -3,6 +3,7 @@ import static org.kohsuke.github.Previews.LOKI; import java.io.IOException; +import java.net.URL; import java.util.Arrays; import java.util.Collection; @@ -51,13 +52,21 @@ public GHRepository getOwner() { public String getName() { return name; } - + + /** + * Returns true if the push to this branch is restricted via branch protection. + */ + @Preview @Deprecated public boolean isProtected() { - return protection; + return protection; } - public String getProtection_url() { - return protection_url; + /** + * Returns API URL that deals with the protection of this branch. + */ + @Preview @Deprecated + public URL getProtectionUrl() { + return GitHub.parseURL(protection_url); } From 6bfeb54f3c5116e241ad8ddd130667cd398bf459 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Mon, 9 Jan 2017 16:14:30 -0800 Subject: [PATCH 222/390] Just exposing permission type enum until there's more to this relation than one property --- src/main/java/org/kohsuke/github/GHPermission.java | 8 +++++++- .../java/org/kohsuke/github/GHPermissionType.java | 11 +++++++++++ src/main/java/org/kohsuke/github/GHRepository.java | 13 +++++++++++-- 3 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 src/main/java/org/kohsuke/github/GHPermissionType.java diff --git a/src/main/java/org/kohsuke/github/GHPermission.java b/src/main/java/org/kohsuke/github/GHPermission.java index 8bc28c719a..51a808dfc0 100644 --- a/src/main/java/org/kohsuke/github/GHPermission.java +++ b/src/main/java/org/kohsuke/github/GHPermission.java @@ -24,11 +24,13 @@ package org.kohsuke.github; +import java.util.Locale; + /** * Permission for a user in a repository. * @see API */ -public class GHPermission { +/*package*/ class GHPermission { private String permission; private GHUser user; @@ -40,6 +42,10 @@ public String getPermission() { return permission; } + public GHPermissionType getPermissionType() { + return Enum.valueOf(GHPermissionType.class, permission.toUpperCase(Locale.ENGLISH)); + } + public GHUser getUser() { return user; } diff --git a/src/main/java/org/kohsuke/github/GHPermissionType.java b/src/main/java/org/kohsuke/github/GHPermissionType.java new file mode 100644 index 0000000000..d3e2bd0909 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHPermissionType.java @@ -0,0 +1,11 @@ +package org.kohsuke.github; + +/** + * @author Kohsuke Kawaguchi + */ +public enum GHPermissionType { + ADMIN, + WRITE, + READ, + NONE +} diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index d3af91a210..cca1d7a8e6 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -486,10 +486,19 @@ public Set getCollaboratorNames() throws IOException { * @throws FileNotFoundException under some conditions (e.g., private repo you can see but are not an admin of); treat as unknown * @throws HttpException with a 403 under other conditions (e.g., public repo you have no special rights to); treat as unknown */ - public GHPermission getPermission(String user) throws IOException { + public GHPermissionType getPermission(String user) throws IOException { GHPermission perm = root.retrieve().withHeader("Accept", "application/vnd.github.korra-preview").to(getApiTailUrl("collaborators/" + user + "/permission"), GHPermission.class); perm.wrapUp(root); - return perm; + return perm.getPermissionType(); + } + + /** + * Obtain permission for a given user in this repository. + * @throws FileNotFoundException under some conditions (e.g., private repo you can see but are not an admin of); treat as unknown + * @throws HttpException with a 403 under other conditions (e.g., public repo you have no special rights to); treat as unknown + */ + public GHPermissionType getPermission(GHUser u) throws IOException { + return getPermission(u.getLogin()); } /** From d1c900a6206ddbeb78616a92841b0667a08a8a11 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Mon, 9 Jan 2017 16:18:40 -0800 Subject: [PATCH 223/390] Marking the fact that these APIs are still in preview and subject to change --- src/main/java/org/kohsuke/github/GHRepository.java | 4 +++- src/main/java/org/kohsuke/github/Previews.java | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index cca1d7a8e6..3235fea3c4 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -486,8 +486,9 @@ public Set getCollaboratorNames() throws IOException { * @throws FileNotFoundException under some conditions (e.g., private repo you can see but are not an admin of); treat as unknown * @throws HttpException with a 403 under other conditions (e.g., public repo you have no special rights to); treat as unknown */ + @Deprecated @Preview public GHPermissionType getPermission(String user) throws IOException { - GHPermission perm = root.retrieve().withHeader("Accept", "application/vnd.github.korra-preview").to(getApiTailUrl("collaborators/" + user + "/permission"), GHPermission.class); + GHPermission perm = root.retrieve().withPreview(KORRA).to(getApiTailUrl("collaborators/" + user + "/permission"), GHPermission.class); perm.wrapUp(root); return perm.getPermissionType(); } @@ -497,6 +498,7 @@ public GHPermissionType getPermission(String user) throws IOException { * @throws FileNotFoundException under some conditions (e.g., private repo you can see but are not an admin of); treat as unknown * @throws HttpException with a 403 under other conditions (e.g., public repo you have no special rights to); treat as unknown */ + @Deprecated @Preview public GHPermissionType getPermission(GHUser u) throws IOException { return getPermission(u.getLogin()); } diff --git a/src/main/java/org/kohsuke/github/Previews.java b/src/main/java/org/kohsuke/github/Previews.java index f95a28b42b..238b062b8b 100644 --- a/src/main/java/org/kohsuke/github/Previews.java +++ b/src/main/java/org/kohsuke/github/Previews.java @@ -7,4 +7,5 @@ static final String LOKI = "application/vnd.github.loki-preview+json"; static final String DRAX = "application/vnd.github.drax-preview+json"; static final String SQUIRREL_GIRL = "application/vnd.github.squirrel-girl-preview"; + static final String KORRA = "application/vnd.github.korra-preview"; } From 911e8d21a717842221f42cd49de0dd543250a807 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Mon, 9 Jan 2017 16:26:58 -0800 Subject: [PATCH 224/390] Made the test case runnable, at least for me --- .../github/AbstractGitHubApiTestBase.java | 15 ++++++++++ src/test/java/org/kohsuke/github/AppTest.java | 13 --------- .../org/kohsuke/github/RepositoryTest.java | 29 ++++++++++--------- 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/src/test/java/org/kohsuke/github/AbstractGitHubApiTestBase.java b/src/test/java/org/kohsuke/github/AbstractGitHubApiTestBase.java index f1753481e7..f32087c0d1 100644 --- a/src/test/java/org/kohsuke/github/AbstractGitHubApiTestBase.java +++ b/src/test/java/org/kohsuke/github/AbstractGitHubApiTestBase.java @@ -1,10 +1,12 @@ package org.kohsuke.github; import org.junit.Assert; +import org.junit.Assume; import org.junit.Before; import org.kohsuke.randname.RandomNameGenerator; import java.io.File; +import java.io.IOException; /** * @author Kohsuke Kawaguchi @@ -25,5 +27,18 @@ public void setUp() throws Exception { } } + protected GHUser getUser() { + try { + return gitHub.getMyself(); + } catch (IOException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + protected void kohsuke() { + String login = getUser().getLogin(); + Assume.assumeTrue(login.equals("kohsuke") || login.equals("kohsuke2")); + } + protected static final RandomNameGenerator rnd = new RandomNameGenerator(); } diff --git a/src/test/java/org/kohsuke/github/AppTest.java b/src/test/java/org/kohsuke/github/AppTest.java index e1d513d739..a20b2eccf3 100755 --- a/src/test/java/org/kohsuke/github/AppTest.java +++ b/src/test/java/org/kohsuke/github/AppTest.java @@ -173,14 +173,6 @@ private GHRepository getTestRepository() throws IOException { return repository; } - private GHUser getUser() { - try { - return gitHub.getMyself(); - } catch (IOException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - @Test public void testListIssues() throws IOException { GHUser u = getUser(); @@ -928,9 +920,4 @@ private void assertBlobContent(InputStream is) throws Exception { assertThat(content,containsString("FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR")); assertThat(content.length(),is(1104)); } - - private void kohsuke() { - String login = getUser().getLogin(); - Assume.assumeTrue(login.equals("kohsuke") || login.equals("kohsuke2")); - } } diff --git a/src/test/java/org/kohsuke/github/RepositoryTest.java b/src/test/java/org/kohsuke/github/RepositoryTest.java index 21625fbf89..9955c34956 100644 --- a/src/test/java/org/kohsuke/github/RepositoryTest.java +++ b/src/test/java/org/kohsuke/github/RepositoryTest.java @@ -1,11 +1,10 @@ package org.kohsuke.github; -import java.io.FileNotFoundException; import org.junit.Test; import org.kohsuke.github.GHRepository.Contributor; +import java.io.FileNotFoundException; import java.io.IOException; -import org.junit.Ignore; /** * @author Kohsuke Kawaguchi @@ -42,19 +41,12 @@ public void listContributors() throws IOException { assertTrue(kohsuke); } - @Ignore("depends on who runs this test whether it can pass or not") @Test public void getPermission() throws Exception { - GHRepository r = gitHub.getOrganization("cloudbeers").getRepository("yolo"); - assertEquals("admin", r.getPermission("jglick").getPermission()); - assertEquals("read", r.getPermission("dude").getPermission()); - r = gitHub.getOrganization("cloudbees").getRepository("private-repo-not-writable-by-me"); - try { - r.getPermission("jglick"); - fail(); - } catch (FileNotFoundException x) { - x.printStackTrace(); // good - } + kohsuke(); + GHRepository r = gitHub.getRepository("github-api-test-org/test-permission"); + assertEquals(GHPermissionType.ADMIN, r.getPermission("kohsuke")); + assertEquals(GHPermissionType.READ, r.getPermission("dude")); r = gitHub.getOrganization("apache").getRepository("groovy"); try { r.getPermission("jglick"); @@ -63,6 +55,17 @@ public void getPermission() throws Exception { x.printStackTrace(); // good assertEquals(403, x.getResponseCode()); } + + if (false) { + // can't easily test this; there's no private repository visible to the test user + r = gitHub.getOrganization("cloudbees").getRepository("private-repo-not-writable-by-me"); + try { + r.getPermission("jglick"); + fail(); + } catch (FileNotFoundException x) { + x.printStackTrace(); // good + } + } } private GHRepository getRepository() throws IOException { From 13184e72e10b9b5f56d3e795f2817940fb994dab Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Mon, 9 Jan 2017 16:37:56 -0800 Subject: [PATCH 225/390] [maven-release-plugin] prepare release github-api-1.83 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 40bf81cbf2..714567f3e6 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.83-SNAPSHOT + 1.83 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - HEAD + github-api-1.83 From 17d1994a532430f86429485f15c8bd108f96dfe7 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Mon, 9 Jan 2017 16:38:02 -0800 Subject: [PATCH 226/390] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 714567f3e6..746efda34c 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.83 + 1.84-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - github-api-1.83 + HEAD From b9b6f4fd4412ab159d23abcdb4f1e5321e9624fa Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Mon, 9 Jan 2017 16:42:03 -0800 Subject: [PATCH 227/390] INFO level logging is harmful as it's reported to stdout by default --- 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 df9353e032..42493db771 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -314,7 +314,7 @@ public GHRateLimit getRateLimit() throws IOException { || headerRateLimit.getResetDate().getTime() < observed.getResetDate().getTime() || headerRateLimit.remaining > observed.remaining) { headerRateLimit = observed; - LOGGER.log(Level.INFO, "Rate limit now: {0}", headerRateLimit); + LOGGER.log(FINE, "Rate limit now: {0}", headerRateLimit); } } } From 6cad4a3c336a091c74dcc8e9f39e4f8318eacabb Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Mon, 9 Jan 2017 16:43:03 -0800 Subject: [PATCH 228/390] static import for conciseness --- src/main/java/org/kohsuke/github/Requester.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index 633e236dec..db70fbd64b 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -58,7 +58,7 @@ import org.apache.commons.lang.StringUtils; import static java.util.Arrays.asList; -import static java.util.logging.Level.FINE; +import static java.util.logging.Level.*; import static org.kohsuke.github.GitHub.MAPPER; /** @@ -352,16 +352,16 @@ private void noteRateLimit(String tailApiUrl) { try { observed.limit = Integer.parseInt(limit); } catch (NumberFormatException e) { - if (LOGGER.isLoggable(Level.FINEST)) { - LOGGER.log(Level.FINEST, "Malformed X-RateLimit-Limit header value " + limit, e); + if (LOGGER.isLoggable(FINEST)) { + LOGGER.log(FINEST, "Malformed X-RateLimit-Limit header value " + limit, e); } return; } try { observed.remaining = Integer.parseInt(remaining); } catch (NumberFormatException e) { - if (LOGGER.isLoggable(Level.FINEST)) { - LOGGER.log(Level.FINEST, "Malformed X-RateLimit-Remaining header value " + remaining, e); + if (LOGGER.isLoggable(FINEST)) { + LOGGER.log(FINEST, "Malformed X-RateLimit-Remaining header value " + remaining, e); } return; } @@ -369,8 +369,8 @@ private void noteRateLimit(String tailApiUrl) { observed.reset = new Date(Long.parseLong(reset)); // this is madness, storing the date as seconds root.updateRateLimit(observed); } catch (NumberFormatException e) { - if (LOGGER.isLoggable(Level.FINEST)) { - LOGGER.log(Level.FINEST, "Malformed X-RateLimit-Reset header value " + reset, e); + if (LOGGER.isLoggable(FINEST)) { + LOGGER.log(FINEST, "Malformed X-RateLimit-Reset header value " + reset, e); } } } From a3a715c3ba48cc85ce797c1cc414f0358d07b4d6 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Mon, 9 Jan 2017 16:50:08 -0800 Subject: [PATCH 229/390] [maven-release-plugin] prepare release github-api-1.84 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 746efda34c..55ba3aee49 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.84-SNAPSHOT + 1.84 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - HEAD + github-api-1.84 From 4ee3086b6dcb46913f1341b2500a4790db5813d6 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Mon, 9 Jan 2017 16:50:15 -0800 Subject: [PATCH 230/390] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 55ba3aee49..462816255a 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.84 + 1.85-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - github-api-1.84 + HEAD From f2e7b40425525f3a32d18e8f6f26bfe08601018c Mon Sep 17 00:00:00 2001 From: Stephen Connolly Date: Tue, 10 Jan 2017 10:15:04 +0000 Subject: [PATCH 231/390] Correct algebra in #327 --- 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 42493db771..ccc18b450e 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -303,7 +303,7 @@ public GHRateLimit getRateLimit() throws IOException { GHRateLimit r = new GHRateLimit(); r.limit = r.remaining = 1000000; long hour = 60L * 60L; // this is madness, storing the date as seconds in a Date object - r.reset = new Date((System.currentTimeMillis() + hour) / 1000L ); + r.reset = new Date(System.currentTimeMillis() / 1000L + hour); return rateLimit = r; } } From 75f0c08ca4b256e6468198d0151a8b09995f31d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20K=C3=BCrten?= Date: Mon, 23 Jan 2017 12:20:35 +0100 Subject: [PATCH 232/390] Fix a bug in the Javadocs (due to copy and paste) --- src/main/java/org/kohsuke/github/GHPullRequest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index 04898039bc..a18dce7741 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -208,7 +208,7 @@ private void populate() throws IOException { } /** - * Retrieves all the commits associated to this pull request. + * Retrieves all the files associated to this pull request. */ public PagedIterable listFiles() { return new PagedIterable() { From 5b156006fb396612e7a931a8292173fdb2bd23f7 Mon Sep 17 00:00:00 2001 From: Greg Gianforcaro Date: Fri, 27 Jan 2017 23:36:54 -0500 Subject: [PATCH 233/390] Add 'Preview' support for MergeMethod on GHPullRequest - Add 'polaris' preview - Add MergeMethod Enum - Add merge method to GHPullRequest which takes a MergeMethod --- .../org/kohsuke/github/GHPullRequest.java | 25 ++++++++++++++++++- .../java/org/kohsuke/github/Previews.java | 1 + .../org/kohsuke/github/PullRequestTest.java | 13 ++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index 04898039bc..8b6404a212 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -23,6 +23,8 @@ */ package org.kohsuke.github; +import static org.kohsuke.github.Previews.POLARIS; + import java.io.IOException; import java.net.URL; import java.util.Collection; @@ -277,7 +279,7 @@ public GHPullRequestReviewComment createReviewComment(String body, String sha, S * Commit message. If null, the default one will be used. */ public void merge(String msg) throws IOException { - merge(msg,null); + merge(msg,(String)null); } /** @@ -294,6 +296,27 @@ public void merge(String msg, String sha) throws IOException { new Requester(root).method("PUT").with("commit_message",msg).with("sha",sha).to(getApiRoute()+"/merge"); } + /** + * Merge this pull request, using the specified merge method. + * + * The equivalent of the big green "Merge pull request" button. + * + * @param msg + * Commit message. If null, the default one will be used. + * @param method + * SHA that pull request head must match to allow merge. + */ + @Preview @Deprecated + public void merge(String msg, MergeMethod method) throws IOException { + new Requester(root).method("PUT") + .withPreview(POLARIS) + .with("commit_message",msg) + .with("merge_method",method) + .to(getApiRoute()+"/merge"); + } + + public enum MergeMethod{ MERGE, SQUASH, REBASE } + private void fetchIssue() throws IOException { if (!fetchedIssueDetails) { new Requester(root).to(getIssuesApiRoute(), this); diff --git a/src/main/java/org/kohsuke/github/Previews.java b/src/main/java/org/kohsuke/github/Previews.java index 238b062b8b..3b7eeb5939 100644 --- a/src/main/java/org/kohsuke/github/Previews.java +++ b/src/main/java/org/kohsuke/github/Previews.java @@ -8,4 +8,5 @@ static final String DRAX = "application/vnd.github.drax-preview+json"; static final String SQUIRREL_GIRL = "application/vnd.github.squirrel-girl-preview"; static final String KORRA = "application/vnd.github.korra-preview"; + static final String POLARIS = "application/vnd.github.polaris-preview"; } diff --git a/src/test/java/org/kohsuke/github/PullRequestTest.java b/src/test/java/org/kohsuke/github/PullRequestTest.java index c7ce77d289..ba8f087197 100644 --- a/src/test/java/org/kohsuke/github/PullRequestTest.java +++ b/src/test/java/org/kohsuke/github/PullRequestTest.java @@ -69,6 +69,19 @@ public void testMergeCommitSHA() throws Exception { fail(); } + @Test + public void testSquashMerge() throws Exception { + String name = rnd.next(); + GHRef masterRef = getRepository().getRef("heads/master"); + GHRef branchRef = getRepository().createRef("refs/heads/" + name, masterRef.getObject().getSha()); + getRepository().createContent(name, name, name, name); + Thread.sleep(1000); + GHPullRequest p = getRepository().createPullRequest(name, name, "master", "## test squash"); + Thread.sleep(1000); + p.merge("squash merge", GHPullRequest.MergeMethod.SQUASH); + branchRef.delete(); + } + @Test // Requires push access to the test repo to pass public void setLabels() throws Exception { From fafe6b0ff7ba04c887171a41862f0bb9150780c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20K=C3=BCrten?= Date: Thu, 9 Feb 2017 18:13:54 +0100 Subject: [PATCH 234/390] Remove unused imports Especially also remove the unsued import of javax.xml.bind.DatatypeConverter from GHContent which is non-public API as of Java 8 --- src/main/java/org/kohsuke/github/GHAuthorization.java | 1 - src/main/java/org/kohsuke/github/GHCommitComment.java | 2 -- src/main/java/org/kohsuke/github/GHContent.java | 2 -- .../java/org/kohsuke/github/GHDeploymentStatusBuilder.java | 1 - src/main/java/org/kohsuke/github/GHHooks.java | 1 - src/main/java/org/kohsuke/github/GHIssueSearchBuilder.java | 2 -- src/main/java/org/kohsuke/github/GHMyself.java | 1 - src/main/java/org/kohsuke/github/GHObject.java | 3 --- .../java/org/kohsuke/github/GHRepositorySearchBuilder.java | 2 -- src/main/java/org/kohsuke/github/GHUserSearchBuilder.java | 2 -- src/main/java/org/kohsuke/github/GitHub.java | 2 -- src/main/java/org/kohsuke/github/HttpConnector.java | 1 - src/main/java/org/kohsuke/github/PagedIterable.java | 1 - src/main/java/org/kohsuke/github/PagedSearchIterable.java | 1 - src/main/java/org/kohsuke/github/Requester.java | 1 - src/test/java/Foo.java | 3 --- src/test/java/org/kohsuke/github/AppTest.java | 3 --- src/test/java/org/kohsuke/github/CommitTest.java | 1 - src/test/java/org/kohsuke/github/GitHubTest.java | 1 - 19 files changed, 31 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHAuthorization.java b/src/main/java/org/kohsuke/github/GHAuthorization.java index 2a9fa39092..e196047776 100644 --- a/src/main/java/org/kohsuke/github/GHAuthorization.java +++ b/src/main/java/org/kohsuke/github/GHAuthorization.java @@ -3,7 +3,6 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.net.URL; import java.util.Collection; -import java.util.Date; import java.util.List; /** diff --git a/src/main/java/org/kohsuke/github/GHCommitComment.java b/src/main/java/org/kohsuke/github/GHCommitComment.java index 3543b5fdb3..646badf5c3 100644 --- a/src/main/java/org/kohsuke/github/GHCommitComment.java +++ b/src/main/java/org/kohsuke/github/GHCommitComment.java @@ -3,8 +3,6 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.io.IOException; import java.net.URL; -import java.util.Date; - import static org.kohsuke.github.Previews.SQUIRREL_GIRL; /** diff --git a/src/main/java/org/kohsuke/github/GHContent.java b/src/main/java/org/kohsuke/github/GHContent.java index 8b6f6fea54..d7a7bd446f 100644 --- a/src/main/java/org/kohsuke/github/GHContent.java +++ b/src/main/java/org/kohsuke/github/GHContent.java @@ -7,8 +7,6 @@ import java.io.IOException; import java.io.InputStream; -import javax.xml.bind.DatatypeConverter; - /** * A Content of a repository. * diff --git a/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java b/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java index 18cf5464ac..f028b6f889 100644 --- a/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java +++ b/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java @@ -1,7 +1,6 @@ package org.kohsuke.github; import java.io.IOException; -import java.util.Locale; public class GHDeploymentStatusBuilder { private final Requester builder; diff --git a/src/main/java/org/kohsuke/github/GHHooks.java b/src/main/java/org/kohsuke/github/GHHooks.java index 6f64587b17..6ecbb04b6e 100644 --- a/src/main/java/org/kohsuke/github/GHHooks.java +++ b/src/main/java/org/kohsuke/github/GHHooks.java @@ -5,7 +5,6 @@ import java.util.Arrays; import java.util.Collection; import java.util.List; -import java.util.Locale; import java.util.Map; /** diff --git a/src/main/java/org/kohsuke/github/GHIssueSearchBuilder.java b/src/main/java/org/kohsuke/github/GHIssueSearchBuilder.java index f9634a59f1..6cefc01678 100644 --- a/src/main/java/org/kohsuke/github/GHIssueSearchBuilder.java +++ b/src/main/java/org/kohsuke/github/GHIssueSearchBuilder.java @@ -1,7 +1,5 @@ package org.kohsuke.github; -import java.util.Locale; - /** * Search issues. * diff --git a/src/main/java/org/kohsuke/github/GHMyself.java b/src/main/java/org/kohsuke/github/GHMyself.java index cc05f03bc5..5ab9b4a270 100644 --- a/src/main/java/org/kohsuke/github/GHMyself.java +++ b/src/main/java/org/kohsuke/github/GHMyself.java @@ -6,7 +6,6 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.TreeMap; diff --git a/src/main/java/org/kohsuke/github/GHObject.java b/src/main/java/org/kohsuke/github/GHObject.java index a81d913a5c..d368af0aec 100644 --- a/src/main/java/org/kohsuke/github/GHObject.java +++ b/src/main/java/org/kohsuke/github/GHObject.java @@ -3,10 +3,7 @@ import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.apache.commons.lang.builder.ReflectionToStringBuilder; -import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; -import org.apache.commons.lang.reflect.FieldUtils; - import java.io.IOException; import java.lang.reflect.Field; import java.net.URL; diff --git a/src/main/java/org/kohsuke/github/GHRepositorySearchBuilder.java b/src/main/java/org/kohsuke/github/GHRepositorySearchBuilder.java index 03b12f5133..642f7f3d95 100644 --- a/src/main/java/org/kohsuke/github/GHRepositorySearchBuilder.java +++ b/src/main/java/org/kohsuke/github/GHRepositorySearchBuilder.java @@ -1,7 +1,5 @@ package org.kohsuke.github; -import java.util.Locale; - /** * Search repositories. * diff --git a/src/main/java/org/kohsuke/github/GHUserSearchBuilder.java b/src/main/java/org/kohsuke/github/GHUserSearchBuilder.java index ca40f4d050..3edcd15065 100644 --- a/src/main/java/org/kohsuke/github/GHUserSearchBuilder.java +++ b/src/main/java/org/kohsuke/github/GHUserSearchBuilder.java @@ -1,7 +1,5 @@ package org.kohsuke.github; -import java.util.Locale; - /** * Search users. * diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index ccc18b450e..3844d8181e 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -47,8 +47,6 @@ import java.util.Map; import java.util.Set; import java.util.TimeZone; -import java.util.concurrent.TimeUnit; -import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.CheckForNull; import javax.annotation.Nonnull; diff --git a/src/main/java/org/kohsuke/github/HttpConnector.java b/src/main/java/org/kohsuke/github/HttpConnector.java index 72f7ce5b05..2d87c148c9 100644 --- a/src/main/java/org/kohsuke/github/HttpConnector.java +++ b/src/main/java/org/kohsuke/github/HttpConnector.java @@ -5,7 +5,6 @@ import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; -import java.util.concurrent.TimeUnit; /** * Pluggability for customizing HTTP request behaviors or using altogether different library. diff --git a/src/main/java/org/kohsuke/github/PagedIterable.java b/src/main/java/org/kohsuke/github/PagedIterable.java index 41c5bfdb0c..1c6eccea36 100644 --- a/src/main/java/org/kohsuke/github/PagedIterable.java +++ b/src/main/java/org/kohsuke/github/PagedIterable.java @@ -1,6 +1,5 @@ package org.kohsuke.github; -import java.io.IOException; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; diff --git a/src/main/java/org/kohsuke/github/PagedSearchIterable.java b/src/main/java/org/kohsuke/github/PagedSearchIterable.java index 1efe49a1ef..f23bd6b58c 100644 --- a/src/main/java/org/kohsuke/github/PagedSearchIterable.java +++ b/src/main/java/org/kohsuke/github/PagedSearchIterable.java @@ -2,7 +2,6 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import java.io.IOException; import java.util.Iterator; /** diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index db70fbd64b..d4bca32d6f 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -48,7 +48,6 @@ import java.util.Locale; import java.util.Map; import java.util.NoSuchElementException; -import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; diff --git a/src/test/java/Foo.java b/src/test/java/Foo.java index 35e5eb5955..540f9fd3ca 100644 --- a/src/test/java/Foo.java +++ b/src/test/java/Foo.java @@ -1,10 +1,7 @@ -import org.kohsuke.github.GHRepository; import org.kohsuke.github.GHRepository.Contributor; import org.kohsuke.github.GHUser; import org.kohsuke.github.GitHub; -import java.util.Collection; - /** * @author Kohsuke Kawaguchi */ diff --git a/src/test/java/org/kohsuke/github/AppTest.java b/src/test/java/org/kohsuke/github/AppTest.java index a20b2eccf3..3d40c78616 100755 --- a/src/test/java/org/kohsuke/github/AppTest.java +++ b/src/test/java/org/kohsuke/github/AppTest.java @@ -5,8 +5,6 @@ import com.google.common.collect.Lists; import org.apache.commons.io.IOUtils; -import org.hamcrest.CoreMatchers; -import org.junit.Assume; import org.junit.Test; import org.kohsuke.github.GHCommit.File; import org.kohsuke.github.GHOrganization.Permission; @@ -16,7 +14,6 @@ import java.net.URL; import java.util.*; import java.util.Map.Entry; -import java.util.concurrent.ExecutionException; import java.util.regex.Pattern; import static org.hamcrest.CoreMatchers.*; diff --git a/src/test/java/org/kohsuke/github/CommitTest.java b/src/test/java/org/kohsuke/github/CommitTest.java index c42fceef41..8e4edb1fed 100644 --- a/src/test/java/org/kohsuke/github/CommitTest.java +++ b/src/test/java/org/kohsuke/github/CommitTest.java @@ -1,7 +1,6 @@ package org.kohsuke.github; import com.google.common.collect.Iterables; -import com.google.common.collect.Iterators; import org.junit.Test; import java.io.IOException; diff --git a/src/test/java/org/kohsuke/github/GitHubTest.java b/src/test/java/org/kohsuke/github/GitHubTest.java index 010adc8b24..a418db5fde 100644 --- a/src/test/java/org/kohsuke/github/GitHubTest.java +++ b/src/test/java/org/kohsuke/github/GitHubTest.java @@ -8,7 +8,6 @@ import java.util.Map; import com.google.common.collect.Iterables; -import com.google.common.collect.Iterators; import org.junit.Test; import static org.hamcrest.CoreMatchers.notNullValue; From 429b26cee8394a81d6ea98ce167150d163f6f865 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20K=C3=BCrten?= Date: Thu, 9 Feb 2017 18:18:07 +0100 Subject: [PATCH 235/390] Ignore eclipse files --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index cb9b4d6a4a..a4bc859689 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,6 @@ target *.iml *.ipr *.iws +/.project +/.classpath +/.settings From 55b00a87f619250ddcd0784ada74fa10625e9980 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 10 Feb 2017 03:28:06 +0300 Subject: [PATCH 236/390] Set 1.6 level. I'm not so old. Signed-off-by: Kanstantsin Shautsou --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 462816255a..0e908df6fe 100644 --- a/pom.xml +++ b/pom.xml @@ -41,13 +41,13 @@ org.codehaus.mojo.signature - java15 + java16 1.0 - ensure-java-1.5-class-library + ensure-java-1.6-class-library test check From be081eec3ff24317bb6423a11230712c2107e2b3 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Fri, 10 Feb 2017 03:33:18 +0300 Subject: [PATCH 237/390] Inject responce headers in GHObject and Exceptions. GH has specific to GET/POST headers required for analysing in case of error. Signed-off-by: Kanstantsin Shautsou --- pom.xml | 6 ++ .../java/org/kohsuke/github/GHObject.java | 13 ++- .../java/org/kohsuke/github/Requester.java | 53 ++++++++++--- .../exception/GHFileNotFoundException.java | 34 ++++++++ .../github/exception/GHIOException.java | 42 ++++++++++ .../java/org/kohsuke/github/GHHookTest.java | 79 +++++++++++++++++++ 6 files changed, 215 insertions(+), 12 deletions(-) create mode 100644 src/main/java/org/kohsuke/github/exception/GHFileNotFoundException.java create mode 100644 src/main/java/org/kohsuke/github/exception/GHIOException.java create mode 100644 src/test/java/org/kohsuke/github/GHHookTest.java diff --git a/pom.xml b/pom.xml index 0e908df6fe..9f372d703d 100644 --- a/pom.xml +++ b/pom.xml @@ -105,6 +105,12 @@ 4.11 test + + org.hamcrest + hamcrest-all + 1.3 + test + com.fasterxml.jackson.core jackson-databind diff --git a/src/main/java/org/kohsuke/github/GHObject.java b/src/main/java/org/kohsuke/github/GHObject.java index a81d913a5c..3a1cde1908 100644 --- a/src/main/java/org/kohsuke/github/GHObject.java +++ b/src/main/java/org/kohsuke/github/GHObject.java @@ -3,14 +3,15 @@ import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.apache.commons.lang.builder.ReflectionToStringBuilder; -import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; -import org.apache.commons.lang.reflect.FieldUtils; +import javax.annotation.CheckForNull; import java.io.IOException; import java.lang.reflect.Field; import java.net.URL; import java.util.Date; +import java.util.List; +import java.util.Map; /** * Most (all?) domain objects in GitHub seems to have these 4 properties. @@ -18,6 +19,9 @@ @SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD"}, justification = "JSON API") public abstract class GHObject { + // not data but information related to data from responce + protected Map> responseHeaderFields; + protected String url; protected int id; protected String created_at; @@ -26,6 +30,11 @@ public abstract class GHObject { /*package*/ GHObject() { } + @CheckForNull + public Map> getResponseHeaderFields() { + return responseHeaderFields; + } + /** * When was this resource created? */ diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index db70fbd64b..64aefe68fe 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -25,6 +25,10 @@ import com.fasterxml.jackson.databind.JsonMappingException; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import org.apache.commons.io.IOUtils; +import org.kohsuke.github.exception.GHFileNotFoundException; +import org.kohsuke.github.exception.GHIOException; + import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; @@ -48,17 +52,18 @@ import java.util.Locale; import java.util.Map; import java.util.NoSuchElementException; -import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.GZIPInputStream; + +import javax.annotation.CheckForNull; import javax.annotation.WillClose; -import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import static java.util.Arrays.asList; -import static java.util.logging.Level.*; +import static java.util.logging.Level.FINE; +import static java.util.logging.Level.FINEST; import static org.kohsuke.github.GitHub.MAPPER; /** @@ -269,7 +274,7 @@ private T _to(String tailApiUrl, Class type, T instance) throws IOExcepti if (nextLinkMatcher.find()) { final String link = nextLinkMatcher.group(1); T nextResult = _to(link, type, instance); - + injectInResult(nextResult); final int resultLength = Array.getLength(result); final int nextResultLength = Array.getLength(nextResult); T concatResult = (T) Array.newInstance(type.getComponentType(), resultLength + nextResultLength); @@ -279,6 +284,7 @@ private T _to(String tailApiUrl, Class type, T instance) throws IOExcepti } } } + injectInResult(result); return result; } catch (IOException e) { handleApiError(e); @@ -579,6 +585,7 @@ private void setRequestMethod(HttpURLConnection uc) throws IOException { throw new IllegalStateException("Failed to set the request method to "+method); } + @CheckForNull private T parse(Class type, T instance) throws IOException { InputStreamReader r = null; int responseCode = -1; @@ -598,12 +605,17 @@ private T parse(Class type, T instance) throws IOException { String data = IOUtils.toString(r); if (type!=null) try { - return MAPPER.readValue(data,type); + final T readValue = MAPPER.readValue(data, type); + injectInResult(readValue); + return readValue; } catch (JsonMappingException e) { throw (IOException)new IOException("Failed to deserialize " +data).initCause(e); } - if (instance!=null) - return MAPPER.readerForUpdating(instance).readValue(data); + if (instance!=null) { + final T readValue = MAPPER.readerForUpdating(instance).readValue(data); + injectInResult(readValue); + return readValue; + } return null; } catch (FileNotFoundException e) { // java.net.URLConnection handles 404 exception has FileNotFoundException, don't wrap exception in HttpException @@ -616,6 +628,26 @@ private T parse(Class type, T instance) throws IOException { } } + private void injectInResult(T readValue) { + if (readValue instanceof GHObject[]) { + for (GHObject ghObject : (GHObject[]) readValue) { + injectInResult(ghObject); + } + } else if (readValue instanceof GHObject) { + injectInResult((GHObject) readValue); + } + } + + private void injectInResult(GHObject readValue) { + try { + final Field field = GHObject.class.getDeclaredField("responseHeaderFields"); + field.setAccessible(true); + field.set(readValue, uc.getHeaderFields()); + } catch (NoSuchFieldException ignore) { + } catch (IllegalAccessException ignore) { + } + } + /** * Handles the "Content-Encoding" header. */ @@ -663,15 +695,16 @@ private InputStream wrapStream(InputStream in) throws IOException { String error = IOUtils.toString(es, "UTF-8"); if (e instanceof FileNotFoundException) { // pass through 404 Not Found to allow the caller to handle it intelligently - throw (IOException) new FileNotFoundException(error).initCause(e); + throw (IOException) new GHFileNotFoundException(error).withResponseHeaderFields(uc).initCause(e); } else if (e instanceof HttpException) { HttpException http = (HttpException) e; throw (IOException) new HttpException(error, http.getResponseCode(), http.getResponseMessage(), http.getUrl(), e); } else { - throw (IOException) new IOException(error).initCause(e); + throw (IOException) new GHIOException(error).withResponceHeaderFields(uc).initCause(e); } - } else + } else { throw e; + } } finally { IOUtils.closeQuietly(es); } diff --git a/src/main/java/org/kohsuke/github/exception/GHFileNotFoundException.java b/src/main/java/org/kohsuke/github/exception/GHFileNotFoundException.java new file mode 100644 index 0000000000..27606de595 --- /dev/null +++ b/src/main/java/org/kohsuke/github/exception/GHFileNotFoundException.java @@ -0,0 +1,34 @@ +package org.kohsuke.github.exception; + +import javax.annotation.CheckForNull; +import java.io.FileNotFoundException; +import java.net.HttpURLConnection; +import java.util.List; +import java.util.Map; + +/** + * Request/responce contains useful metadata. + * Custom exception allows store info for next diagnostics. + * + * @author Kanstantsin Shautsou + */ +public class GHFileNotFoundException extends FileNotFoundException { + protected Map> responseHeaderFields; + + public GHFileNotFoundException() { + } + + public GHFileNotFoundException(String s) { + super(s); + } + + @CheckForNull + public Map> getResponseHeaderFields() { + return responseHeaderFields; + } + + public GHFileNotFoundException withResponseHeaderFields(HttpURLConnection urlConnection) { + this.responseHeaderFields = urlConnection.getHeaderFields(); + return this; + } +} diff --git a/src/main/java/org/kohsuke/github/exception/GHIOException.java b/src/main/java/org/kohsuke/github/exception/GHIOException.java new file mode 100644 index 0000000000..7bb614092e --- /dev/null +++ b/src/main/java/org/kohsuke/github/exception/GHIOException.java @@ -0,0 +1,42 @@ +package org.kohsuke.github.exception; + +import javax.annotation.CheckForNull; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.util.List; +import java.util.Map; + +/** + * Request/responce contains useful metadata. + * Custom exception allows store info for next diagnostics. + * + * @author Kanstantsin Shautsou + */ +public class GHIOException extends IOException { + protected Map> responceHeaderFields; + + public GHIOException() { + } + + public GHIOException(String message) { + super(message); + } + + public GHIOException(String message, Throwable cause) { + super(message, cause); + } + + public GHIOException(Throwable cause) { + super(cause); + } + + @CheckForNull + public Map> getResponceHeaderFields() { + return responceHeaderFields; + } + + public GHIOException withResponceHeaderFields(HttpURLConnection urlConnection) { + this.responceHeaderFields = urlConnection.getHeaderFields(); + return this; + } +} diff --git a/src/test/java/org/kohsuke/github/GHHookTest.java b/src/test/java/org/kohsuke/github/GHHookTest.java new file mode 100644 index 0000000000..2cbab48cb7 --- /dev/null +++ b/src/test/java/org/kohsuke/github/GHHookTest.java @@ -0,0 +1,79 @@ +package org.kohsuke.github; + +import org.apache.commons.lang.StringUtils; +import org.junit.Ignore; +import org.junit.Test; +import org.kohsuke.github.exception.GHFileNotFoundException; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import static java.util.Collections.singletonList; +import static java.util.Collections.singletonMap; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.hasKey; +import static org.hamcrest.Matchers.hasValue; +import static org.hamcrest.core.IsInstanceOf.instanceOf; +import static org.junit.Assert.assertThat; + + +/** + * @author Kanstantsin Shautsou + */ +public class GHHookTest { + + @Ignore + @Test + public void exposeResponceHeaders() throws Exception { + String user1Login = "KostyaSha-auto"; + String user1Pass = "secret"; + + String clientId = "90140219451"; + String clientSecret = "1451245425"; + + String orgRepo = "KostyaSha-org/test"; + + // some login based user that has access to application + final GitHub gitHub = GitHub.connectUsingPassword(user1Login, user1Pass); + gitHub.getMyself(); + + // we request read + final List scopes = Arrays.asList("repo", "read:org", "user:email", "read:repo_hook"); + + // application creates token with scopes + final GHAuthorization auth = gitHub.createOrGetAuth(clientId, clientSecret, scopes, "", ""); + String token = auth.getToken(); + if (StringUtils.isEmpty(token)) { + gitHub.deleteAuth(auth.getId()); + token = gitHub.createOrGetAuth(clientId, clientSecret, scopes, "", "").getToken(); + } + + /// now create connection using token + final GitHub gitHub2 = GitHub.connectUsingOAuth(token); + // some repo in organisation + final GHRepository repository = gitHub2.getRepository(orgRepo); + + // doesn't fail because we have read access + final List hooks = repository.getHooks(); + + try { + // fails because application isn't approved in organisation and you can find it only after doing real call + final GHHook hook = repository.createHook( + "my-hook", + singletonMap("url", "http://localhost"), + singletonList(GHEvent.PUSH), + true + ); + } catch (IOException ex) { + assertThat(ex, instanceOf(GHFileNotFoundException.class)); + final GHFileNotFoundException ghFileNotFoundException = (GHFileNotFoundException) ex; + final Map> responseHeaderFields = ghFileNotFoundException.getResponseHeaderFields(); + assertThat(responseHeaderFields, hasKey("X-Accepted-OAuth-Scopes")); + assertThat(responseHeaderFields.get("X-Accepted-OAuth-Scopes"), + hasItem("admin:repo_hook, public_repo, repo, write:repo_hook") + ); + } + } +} From 166e26d10184b3e2a1cb2c086d6b9ed3e9b50305 Mon Sep 17 00:00:00 2001 From: kamontat Date: Sun, 19 Feb 2017 23:57:44 +0700 Subject: [PATCH 238/390] add latest release --- src/main/java/org/kohsuke/github/GHRepository.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 74fbb4d665..4a71f64ace 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -298,6 +298,10 @@ public GHRef createRef(String name, String sha) throws IOException { public List getReleases() throws IOException { return listReleases().asList(); } + + public GHRelease latestRelease() throws IOException { + return root.retrieve().to(getApiTailUrl("releases/latest"), GHRelease.class).wrap(this); + } public PagedIterable listReleases() throws IOException { return new PagedIterable() { From fd859815b039a84c3dd53e38ff8d41fefc2c2b23 Mon Sep 17 00:00:00 2001 From: kamontat Date: Mon, 20 Feb 2017 09:36:28 +0700 Subject: [PATCH 239/390] fixed indent, rename to getLastestRelease --- src/main/java/org/kohsuke/github/GHRepository.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 4a71f64ace..22ab01e796 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -299,9 +299,9 @@ public List getReleases() throws IOException { return listReleases().asList(); } - public GHRelease latestRelease() throws IOException { + public GHRelease getLatestRelease() throws IOException { return root.retrieve().to(getApiTailUrl("releases/latest"), GHRelease.class).wrap(this); - } + } public PagedIterable listReleases() throws IOException { return new PagedIterable() { From 1cffea892b3b2927cf4733259c3095ec04309b4d Mon Sep 17 00:00:00 2001 From: kamontat Date: Mon, 20 Feb 2017 10:20:08 +0700 Subject: [PATCH 240/390] add test --- .../org/kohsuke/github/RepositoryTest.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/test/java/org/kohsuke/github/RepositoryTest.java b/src/test/java/org/kohsuke/github/RepositoryTest.java index 9955c34956..728f94a834 100644 --- a/src/test/java/org/kohsuke/github/RepositoryTest.java +++ b/src/test/java/org/kohsuke/github/RepositoryTest.java @@ -67,6 +67,32 @@ public void getPermission() throws Exception { } } } + + + + @Test + public void LatestRepositoryExist() { + try { + // add the repository that have latest release + GHRelease release = gitHub.getRepository("kamontat/CheckIDNumber").getLatestRelease(); + assertEquals("v3.0", release.getTagName()); + } catch (IOException e) { + e.printStackTrace(); + fail(); + } + } + + @Test + public void LatestRepositoryNotExist() { + try { + // add the repository that `NOT` have latest release + GHRelease release = gitHub.getRepository("kamontat/Java8Example").getLatestRelease(); + assertNull(release); + } catch (IOException e) { + e.printStackTrace(); + fail(); + } + } private GHRepository getRepository() throws IOException { return gitHub.getOrganization("github-api-test-org").getRepository("jenkins"); From 5554332b5be0df4b801813a903c8ab98aef8d0b7 Mon Sep 17 00:00:00 2001 From: kamontat Date: Mon, 20 Feb 2017 10:20:53 +0700 Subject: [PATCH 241/390] add return null if latest release not found --- src/main/java/org/kohsuke/github/GHRepository.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 22ab01e796..f233f8b4fe 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -300,7 +300,11 @@ public List getReleases() throws IOException { } public GHRelease getLatestRelease() throws IOException { - return root.retrieve().to(getApiTailUrl("releases/latest"), GHRelease.class).wrap(this); + try { + return root.retrieve().to(getApiTailUrl("releases/latest"), GHRelease.class).wrap(this); + } catch (FileNotFoundException e) { + return null; // no latest release + } } public PagedIterable listReleases() throws IOException { From 2627dc5ee4ed60c0250ce5a9e99d586d480603f2 Mon Sep 17 00:00:00 2001 From: Stephen Connolly Date: Thu, 23 Feb 2017 12:30:17 +0000 Subject: [PATCH 242/390] Ensure that connections are closed for error responses - This was endless fun to trace, but I found it at last. This should stop the `WARNING: A connection to https://api.github.com/ was leaked. Did you forget to close a response body?` messages in the logs when using the OkHttpConnector. --- src/main/java/org/kohsuke/github/GitHub.java | 17 +++++++-- .../java/org/kohsuke/github/Requester.java | 38 +++++++++---------- 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index ccc18b450e..896fb36c63 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -47,13 +47,12 @@ import java.util.Map; import java.util.Set; import java.util.TimeZone; -import java.util.concurrent.TimeUnit; -import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.CheckForNull; import javax.annotation.Nonnull; import org.apache.commons.codec.Charsets; import org.apache.commons.codec.binary.Base64; +import org.apache.commons.io.IOUtils; import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.ANY; import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE; @@ -703,8 +702,18 @@ private boolean isPrivateModeEnabled() { Strict-Transport-Security: max-age=31536000; includeSubdomains; preload X-Content-Type-Options: nosniff */ - return uc.getResponseCode() == HTTP_UNAUTHORIZED - && uc.getHeaderField("X-GitHub-Media-Type") != null; + try { + return uc.getResponseCode() == HTTP_UNAUTHORIZED + && uc.getHeaderField("X-GitHub-Media-Type") != null; + } finally { + // ensure that the connection opened by getResponseCode gets closed + try { + IOUtils.closeQuietly(uc.getInputStream()); + } catch (IOException ignore) { + // ignore + } + IOUtils.closeQuietly(uc.getErrorStream()); + } } catch (IOException e) { return false; } diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index db70fbd64b..3cd338b8c2 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -48,7 +48,6 @@ import java.util.Locale; import java.util.Map; import java.util.NoSuchElementException; -import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -642,6 +641,24 @@ private InputStream wrapStream(InputStream in) throws IOException { " handling exception " + e, e); throw e; } + InputStream es = wrapStream(uc.getErrorStream()); + if (es != null) { + try { + String error = IOUtils.toString(es, "UTF-8"); + if (e instanceof FileNotFoundException) { + // pass through 404 Not Found to allow the caller to handle it intelligently + e = (IOException) new FileNotFoundException(error).initCause(e); + } else if (e instanceof HttpException) { + HttpException http = (HttpException) e; + e = new HttpException(error, http.getResponseCode(), http.getResponseMessage(), + http.getUrl(), e); + } else { + e = (IOException) new IOException(error).initCause(e); + } + } finally { + IOUtils.closeQuietly(es); + } + } if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) // 401 / Unauthorized == bad creds throw e; @@ -657,24 +674,7 @@ private InputStream wrapStream(InputStream in) throws IOException { return; } - InputStream es = wrapStream(uc.getErrorStream()); - try { - if (es!=null) { - String error = IOUtils.toString(es, "UTF-8"); - if (e instanceof FileNotFoundException) { - // pass through 404 Not Found to allow the caller to handle it intelligently - throw (IOException) new FileNotFoundException(error).initCause(e); - } else if (e instanceof HttpException) { - HttpException http = (HttpException) e; - throw (IOException) new HttpException(error, http.getResponseCode(), http.getResponseMessage(), http.getUrl(), e); - } else { - throw (IOException) new IOException(error).initCause(e); - } - } else - throw e; - } finally { - IOUtils.closeQuietly(es); - } + throw e; } private static final List METHODS_WITHOUT_BODY = asList("GET", "DELETE"); From 3d03659508a9230cd19bb0be21b2fe144c3e51dd Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Tue, 28 Feb 2017 21:06:08 -0800 Subject: [PATCH 243/390] [maven-release-plugin] prepare release github-api-1.85 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 462816255a..b008da989a 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.85-SNAPSHOT + 1.85 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - HEAD + github-api-1.85 From e9b59c6bef4a461aa0d2f54653439f13436d1d06 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Tue, 28 Feb 2017 21:06:14 -0800 Subject: [PATCH 244/390] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index b008da989a..1a31c32433 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.85 + 1.86-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - github-api-1.85 + HEAD From 64af13f40d7c97862a1379758e3c157445c7095e Mon Sep 17 00:00:00 2001 From: mdeverdelhan Date: Thu, 30 Mar 2017 12:55:55 +0200 Subject: [PATCH 245/390] Add the Commit search API (still in preview) --- .../kohsuke/github/GHCommitSearchBuilder.java | 115 ++++++++++++++++++ .../org/kohsuke/github/GHQueryBuilder.java | 2 +- src/main/java/org/kohsuke/github/GitHub.java | 8 ++ .../java/org/kohsuke/github/Previews.java | 1 + src/test/java/org/kohsuke/github/AppTest.java | 6 + 5 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java diff --git a/src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java b/src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java new file mode 100644 index 0000000000..790c06149d --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java @@ -0,0 +1,115 @@ +package org.kohsuke.github; + +import java.util.Locale; + +/** + * Search commits. + * + * @author Marc de Verdelhan + * @see GitHub#searchCommits() + */ +@Preview @Deprecated +public class GHCommitSearchBuilder extends GHSearchBuilder { + /*package*/ GHCommitSearchBuilder(GitHub root) { + super(root,CommitSearchResult.class); + req = req.withPreview(Previews.CLOAK); + } + + /** + * Search terms. + */ + public GHCommitSearchBuilder q(String term) { + super.q(term); + return this; + } + + public GHCommitSearchBuilder author(String v) { + return q("author:"+v); + } + + public GHCommitSearchBuilder committer(String v) { + return q("committer:"+v); + } + + public GHCommitSearchBuilder authorName(String v) { + return q("author-name:"+v); + } + + public GHCommitSearchBuilder committerName(String v) { + return q("committer-name:"+v); + } + + public GHCommitSearchBuilder authorEmail(String v) { + return q("author-email:"+v); + } + + public GHCommitSearchBuilder committerEmail(String v) { + return q("committer-email:"+v); + } + + public GHCommitSearchBuilder authorDate(String v) { + return q("author-date:"+v); + } + + public GHCommitSearchBuilder committerDate(String v) { + return q("committer-date:"+v); + } + + public GHCommitSearchBuilder merge(boolean merge) { + return q("merge:"+Boolean.valueOf(merge).toString().toLowerCase()); + } + + public GHCommitSearchBuilder hash(String v) { + return q("hash:"+v); + } + + public GHCommitSearchBuilder parent(String v) { + return q("parent:"+v); + } + + public GHCommitSearchBuilder tree(String v) { + return q("tree:"+v); + } + + public GHCommitSearchBuilder is(String v) { + return q("is:"+v); + } + + public GHCommitSearchBuilder user(String v) { + return q("user:"+v); + } + + public GHCommitSearchBuilder org(String v) { + return q("org:"+v); + } + + public GHCommitSearchBuilder repo(String v) { + return q("repo:"+v); + } + + public GHCommitSearchBuilder order(GHDirection v) { + req.with("order",v); + return this; + } + + public GHCommitSearchBuilder sort(Sort sort) { + req.with("sort",sort); + return this; + } + + public enum Sort { AUTHOR_DATE, COMMITTER_DATE } + + private static class CommitSearchResult extends SearchResult { + private GHCommit[] items; + + @Override + /*package*/ GHCommit[] getItems(GitHub root) { + return items; + } + } + + @Override + protected String getApiUrl() { + return "/search/commits"; + } +} diff --git a/src/main/java/org/kohsuke/github/GHQueryBuilder.java b/src/main/java/org/kohsuke/github/GHQueryBuilder.java index bb85fbbe95..5eca4278a1 100644 --- a/src/main/java/org/kohsuke/github/GHQueryBuilder.java +++ b/src/main/java/org/kohsuke/github/GHQueryBuilder.java @@ -7,7 +7,7 @@ */ public abstract class GHQueryBuilder { protected final GitHub root; - protected final Requester req; + protected Requester req; /*package*/ GHQueryBuilder(GitHub root) { this.root = root; diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 896fb36c63..49c860e4dc 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -719,6 +719,14 @@ private boolean isPrivateModeEnabled() { } } + /** + * Search commits. + */ + @Preview @Deprecated + public GHCommitSearchBuilder searchCommits() { + return new GHCommitSearchBuilder(this); + } + /** * Search issues. */ diff --git a/src/main/java/org/kohsuke/github/Previews.java b/src/main/java/org/kohsuke/github/Previews.java index 238b062b8b..b663122d4b 100644 --- a/src/main/java/org/kohsuke/github/Previews.java +++ b/src/main/java/org/kohsuke/github/Previews.java @@ -8,4 +8,5 @@ static final String DRAX = "application/vnd.github.drax-preview+json"; static final String SQUIRREL_GIRL = "application/vnd.github.squirrel-girl-preview"; static final String KORRA = "application/vnd.github.korra-preview"; + static final String CLOAK = "application/vnd.github.cloak-preview"; } diff --git a/src/test/java/org/kohsuke/github/AppTest.java b/src/test/java/org/kohsuke/github/AppTest.java index a20b2eccf3..08a6188d66 100755 --- a/src/test/java/org/kohsuke/github/AppTest.java +++ b/src/test/java/org/kohsuke/github/AppTest.java @@ -685,6 +685,12 @@ public void testMemberPagenation() throws IOException { assertFalse(all.isEmpty()); } + @Test + public void testCommitSearch() throws IOException { + PagedSearchIterable r = gitHub.searchCommits().author("kohsuke").list(); + assertTrue(r.getTotalCount() > 0); + } + @Test public void testIssueSearch() throws IOException { PagedSearchIterable r = gitHub.searchIssues().mentions("kohsuke").isOpen().list(); From 44d4d0d7673c3d8e88fbeb92236b4de1a17944c3 Mon Sep 17 00:00:00 2001 From: Stephen Connolly Date: Thu, 30 Mar 2017 12:13:23 +0100 Subject: [PATCH 246/390] Add support for PR reviews preview --- .../org/kohsuke/github/GHPullRequest.java | 77 +++++++++ .../kohsuke/github/GHPullRequestReview.java | 147 ++++++++++++++++++ .../github/GHPullRequestReviewComment.java | 8 + .../github/GHPullRequestReviewState.java | 19 +++ .../github/AbstractGitHubApiTestBase.java | 13 +- .../org/kohsuke/github/PullRequestTest.java | 30 ++++ 6 files changed, 293 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/kohsuke/github/GHPullRequestReview.java create mode 100644 src/main/java/org/kohsuke/github/GHPullRequestReviewState.java diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index 04898039bc..9e6bb3e1a7 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -25,8 +25,12 @@ import java.io.IOException; import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Date; +import java.util.List; +import javax.annotation.CheckForNull; /** * A pull request. @@ -223,6 +227,27 @@ protected void wrapUp(GHPullRequestFileDetail[] page) { }; } + /** + * Retrieves all the reviews associated to this pull request. + */ + public PagedIterable listReviews() { + return new PagedIterable() { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve() + .withPreview("application/vnd.github.black-cat-preview+json") + .asIterator(String.format("%s/reviews", getApiRoute()), + GHPullRequestReview[].class, pageSize)) { + @Override + protected void wrapUp(GHPullRequestReview[] page) { + for (GHPullRequestReview r: page) { + r.wrapUp(GHPullRequest.this); + } + } + }; + } + }; + } + /** * Obtains all the review comments associated with this pull request. */ @@ -259,6 +284,34 @@ protected void wrapUp(GHPullRequestCommitDetail[] page) { }; } + @Preview + @Deprecated + public GHPullRequestReview createReview(String body, @CheckForNull GHPullRequestReviewState event, + GHPullRequestReviewComment... comments) + throws IOException { + return createReview(body, event, Arrays.asList(comments)); + } + + @Preview + @Deprecated + public GHPullRequestReview createReview(String body, @CheckForNull GHPullRequestReviewState event, + List comments) + throws IOException { + if (event == null) { + event = GHPullRequestReviewState.PENDING; + } + List draftComments = new ArrayList(comments.size()); + for (GHPullRequestReviewComment c : comments) { + draftComments.add(new DraftReviewComment(c.getBody(), c.getPath(), c.getPosition())); + } + return new Requester(root).method("POST") + .with("body", body) + //.with("event", event.name()) + ._with("comments", draftComments) + .withPreview("application/vnd.github.black-cat-preview+json") + .to(getApiRoute() + "/reviews", GHPullRequestReview.class).wrapUp(this); + } + public GHPullRequestReviewComment createReviewComment(String body, String sha, String path, int position) throws IOException { return new Requester(root).method("POST") .with("body", body) @@ -300,4 +353,28 @@ private void fetchIssue() throws IOException { fetchedIssueDetails = true; } } + + private static class DraftReviewComment { + private String body; + private String path; + private int position; + + public DraftReviewComment(String body, String path, int position) { + this.body = body; + this.path = path; + this.position = position; + } + + public String getBody() { + return body; + } + + public String getPath() { + return path; + } + + public int getPosition() { + return position; + } + } } diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReview.java b/src/main/java/org/kohsuke/github/GHPullRequestReview.java new file mode 100644 index 0000000000..1fb57d4bf9 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHPullRequestReview.java @@ -0,0 +1,147 @@ +/* + * The MIT License + * + * Copyright (c) 2017, CloudBees, Inc. + * + * 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 to the pull request + * + * @see GHPullRequest#listReviews() + * @see GHPullRequest#createReview(String, GHPullRequestReviewState, GHPullRequestReviewComment...) + */ +public class GHPullRequestReview extends GHObject { + GHPullRequest owner; + + private String body; + private GHUser user; + private String commit_id; + private GHPullRequestReviewState state; + + /*package*/ GHPullRequestReview wrapUp(GHPullRequest owner) { + this.owner = owner; + return this; + } + + /** + * Gets the pull request to which this review is associated. + */ + public GHPullRequest getParent() { + return owner; + } + + /** + * The comment itself. + */ + public String getBody() { + return body; + } + + /** + * Gets the user who posted this review. + */ + public GHUser getUser() throws IOException { + return owner.root.getUser(user.getLogin()); + } + + public String getCommitId() { + return commit_id; + } + + public GHPullRequestReviewState getState() { + return state; + } + + @Override + public URL getHtmlUrl() { + return null; + } + + protected String getApiRoute() { + return owner.getApiRoute()+"/reviews/"+id; + } + + /** + * Updates the comment. + */ + @Preview + @Deprecated + public void submit(String body, GHPullRequestReviewState event) throws IOException { + new Requester(owner.root).method("POST") + .with("body", body) + .with("event", event.action()) + .withPreview("application/vnd.github.black-cat-preview+json") + .to(getApiRoute()+"/events",this); + this.body = body; + this.state = event; + } + + /** + * Deletes this review. + */ + @Preview + @Deprecated + public void delete() throws IOException { + new Requester(owner.root).method("DELETE") + .withPreview("application/vnd.github.black-cat-preview+json") + .to(getApiRoute()); + } + + /** + * Dismisses this review. + */ + @Preview + @Deprecated + public void dismiss(String message) throws IOException { + new Requester(owner.root).method("PUT") + .with("message", message) + .withPreview("application/vnd.github.black-cat-preview+json") + .to(getApiRoute()+"/dismissals"); + state = GHPullRequestReviewState.DISMISSED; + } + + /** + * Obtains all the review comments associated with this pull request review. + */ + @Preview + @Deprecated + public PagedIterable listReviewComments() throws IOException { + return new PagedIterable() { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator( + owner.root.retrieve() + .withPreview("application/vnd.github.black-cat-preview+json") + .asIterator(getApiRoute() + "/comments", + GHPullRequestReviewComment[].class, pageSize)) { + protected void wrapUp(GHPullRequestReviewComment[] page) { + for (GHPullRequestReviewComment c : page) + c.wrapUp(owner); + } + }; + } + }; + } + +} diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java b/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java index 05784b5078..33097bc29d 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java @@ -44,6 +44,14 @@ public class GHPullRequestReviewComment extends GHObject implements Reactable { private int position; private int originalPosition; + public static GHPullRequestReviewComment draft(String body, String path, int position) { + GHPullRequestReviewComment result = new GHPullRequestReviewComment(); + result.body = body; + result.path = path; + result.position = position; + return result; + } + /*package*/ GHPullRequestReviewComment wrapUp(GHPullRequest owner) { this.owner = owner; return this; diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReviewState.java b/src/main/java/org/kohsuke/github/GHPullRequestReviewState.java new file mode 100644 index 0000000000..fca3fabfb3 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHPullRequestReviewState.java @@ -0,0 +1,19 @@ +package org.kohsuke.github; + +public enum GHPullRequestReviewState { + PENDING(null), + APPROVED("APPROVE"), + REQUEST_CHANGES("REQUEST_CHANGES"), + COMMENTED("COMMENT"), + DISMISSED(null); + + private final String _action; + + GHPullRequestReviewState(String action) { + _action = action; + } + + public String action() { + return _action; + } +} diff --git a/src/test/java/org/kohsuke/github/AbstractGitHubApiTestBase.java b/src/test/java/org/kohsuke/github/AbstractGitHubApiTestBase.java index f32087c0d1..a7afb38fd7 100644 --- a/src/test/java/org/kohsuke/github/AbstractGitHubApiTestBase.java +++ b/src/test/java/org/kohsuke/github/AbstractGitHubApiTestBase.java @@ -1,5 +1,8 @@ package org.kohsuke.github; +import java.io.FileInputStream; +import java.util.Properties; +import org.apache.commons.io.IOUtils; import org.junit.Assert; import org.junit.Assume; import org.junit.Before; @@ -19,9 +22,17 @@ public abstract class AbstractGitHubApiTestBase extends Assert { public void setUp() throws Exception { File f = new File(System.getProperty("user.home"), ".github.kohsuke2"); if (f.exists()) { + Properties props = new Properties(); + FileInputStream in = null; + try { + in = new FileInputStream(f); + props.load(in); + } finally { + IOUtils.closeQuietly(in); + } // 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()).withRateLimitHandler(RateLimitHandler.FAIL).build(); + gitHub = GitHubBuilder.fromProperties(props).withRateLimitHandler(RateLimitHandler.FAIL).build(); } else { gitHub = GitHubBuilder.fromCredentials().withRateLimitHandler(RateLimitHandler.FAIL).build(); } diff --git a/src/test/java/org/kohsuke/github/PullRequestTest.java b/src/test/java/org/kohsuke/github/PullRequestTest.java index c7ce77d289..ce09b2ab13 100644 --- a/src/test/java/org/kohsuke/github/PullRequestTest.java +++ b/src/test/java/org/kohsuke/github/PullRequestTest.java @@ -7,6 +7,9 @@ import java.util.Collection; import java.util.List; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; + /** * @author Kohsuke Kawaguchi */ @@ -26,6 +29,33 @@ public void createPullRequestComment() throws Exception { p.comment("Some comment"); } + @Test + public void testPullRequestReviews() throws Exception { + String name = rnd.next(); + GHPullRequest p = getRepository().createPullRequest(name, "stable", "master", "## test"); + GHPullRequestReview draftReview = p.createReview("Some draft review", null, + GHPullRequestReviewComment.draft("Some niggle", "changelog.html", 1) + ); + assertThat(draftReview.getState(), is(GHPullRequestReviewState.PENDING)); + assertThat(draftReview.getBody(), is("Some draft review")); + assertThat(draftReview.getCommitId(), notNullValue()); + List reviews = p.listReviews().asList(); + assertThat(reviews.size(), is(1)); + GHPullRequestReview review = reviews.get(0); + assertThat(review.getState(), is(GHPullRequestReviewState.PENDING)); + assertThat(review.getBody(), is("Some draft review")); + assertThat(review.getCommitId(), notNullValue()); + review.submit("Some review comment", GHPullRequestReviewState.COMMENTED); + List comments = review.listReviewComments().asList(); + assertEquals(1, comments.size()); + GHPullRequestReviewComment comment = comments.get(0); + assertEquals("Some niggle", comment.getBody()); + review = p.createReview("Some new review", null, + GHPullRequestReviewComment.draft("Some niggle", "changelog.html", 1) + ); + review.delete(); + } + @Test public void testPullRequestReviewComments() throws Exception { String name = rnd.next(); From c9b5074bc40efc6a97deef5f48812807dc3a305e Mon Sep 17 00:00:00 2001 From: mdeverdelhan Date: Thu, 11 May 2017 12:32:34 +0200 Subject: [PATCH 247/390] Fix the wrapping of retrieved commits (owner/repository) --- .../kohsuke/github/GHCommitSearchBuilder.java | 23 +++++++++++++++++++ src/test/java/org/kohsuke/github/AppTest.java | 3 +++ 2 files changed, 26 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java b/src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java index 790c06149d..1385b0c67e 100644 --- a/src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java +++ b/src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java @@ -1,7 +1,10 @@ package org.kohsuke.github; +import java.io.IOException; import java.util.Locale; +import org.apache.commons.lang.StringUtils; + /** * Search commits. * @@ -104,9 +107,29 @@ private static class CommitSearchResult extends SearchResult { @Override /*package*/ GHCommit[] getItems(GitHub root) { + for (GHCommit commit : items) { + String repoName = getRepoName(commit.url); + try { + GHRepository repo = root.getRepository(repoName); + commit.wrapUp(repo); + } catch (IOException ioe) {} + } return items; } } + + /** + * @param commitUrl a commit URL + * @return the repo name ("username/reponame") + */ + private static String getRepoName(String commitUrl) { + if (StringUtils.isBlank(commitUrl)) { + return null; + } + int indexOfUsername = (GitHub.GITHUB_URL + "/repos/").length(); + String[] tokens = commitUrl.substring(indexOfUsername).split("/", 3); + return tokens[0] + '/' + tokens[1]; + } @Override protected String getApiUrl() { diff --git a/src/test/java/org/kohsuke/github/AppTest.java b/src/test/java/org/kohsuke/github/AppTest.java index 08a6188d66..248bd0ef11 100755 --- a/src/test/java/org/kohsuke/github/AppTest.java +++ b/src/test/java/org/kohsuke/github/AppTest.java @@ -689,6 +689,9 @@ public void testMemberPagenation() throws IOException { public void testCommitSearch() throws IOException { PagedSearchIterable r = gitHub.searchCommits().author("kohsuke").list(); assertTrue(r.getTotalCount() > 0); + + GHCommit firstCommit = r.iterator().next(); + assertTrue(firstCommit.getFiles().size() > 0); } @Test From 3a40af8871bfc992a920d765e9054454dc842726 Mon Sep 17 00:00:00 2001 From: Jesse Glick Date: Mon, 12 Jun 2017 10:28:25 -0400 Subject: [PATCH 248/390] [JENKINS-36240] /repos/:owner/:repo/collaborators/:username/permission no longer requires korra preview. --- src/main/java/org/kohsuke/github/GHRepository.java | 4 +--- src/main/java/org/kohsuke/github/Previews.java | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 74fbb4d665..021c3f6ca2 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -486,9 +486,8 @@ public Set getCollaboratorNames() throws IOException { * @throws FileNotFoundException under some conditions (e.g., private repo you can see but are not an admin of); treat as unknown * @throws HttpException with a 403 under other conditions (e.g., public repo you have no special rights to); treat as unknown */ - @Deprecated @Preview public GHPermissionType getPermission(String user) throws IOException { - GHPermission perm = root.retrieve().withPreview(KORRA).to(getApiTailUrl("collaborators/" + user + "/permission"), GHPermission.class); + GHPermission perm = root.retrieve().to(getApiTailUrl("collaborators/" + user + "/permission"), GHPermission.class); perm.wrapUp(root); return perm.getPermissionType(); } @@ -498,7 +497,6 @@ public GHPermissionType getPermission(String user) throws IOException { * @throws FileNotFoundException under some conditions (e.g., private repo you can see but are not an admin of); treat as unknown * @throws HttpException with a 403 under other conditions (e.g., public repo you have no special rights to); treat as unknown */ - @Deprecated @Preview public GHPermissionType getPermission(GHUser u) throws IOException { return getPermission(u.getLogin()); } diff --git a/src/main/java/org/kohsuke/github/Previews.java b/src/main/java/org/kohsuke/github/Previews.java index 238b062b8b..f95a28b42b 100644 --- a/src/main/java/org/kohsuke/github/Previews.java +++ b/src/main/java/org/kohsuke/github/Previews.java @@ -7,5 +7,4 @@ static final String LOKI = "application/vnd.github.loki-preview+json"; static final String DRAX = "application/vnd.github.drax-preview+json"; static final String SQUIRREL_GIRL = "application/vnd.github.squirrel-girl-preview"; - static final String KORRA = "application/vnd.github.korra-preview"; } From cb7620395a18caace541e66b7637194d89ef8d21 Mon Sep 17 00:00:00 2001 From: Jesse Glick Date: Wed, 28 Jun 2017 17:09:37 -0400 Subject: [PATCH 249/390] [JENKINS-45142] Retry connections after getting SocketTimeoutException. --- src/main/java/org/kohsuke/github/Requester.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index 3cd338b8c2..d7d6239190 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -36,6 +36,7 @@ import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.ProtocolException; +import java.net.SocketTimeoutException; import java.net.URL; import java.net.URLEncoder; import java.util.ArrayList; @@ -57,6 +58,7 @@ import org.apache.commons.lang.StringUtils; import static java.util.Arrays.asList; +import java.util.logging.Level; import static java.util.logging.Level.*; import static org.kohsuke.github.GitHub.MAPPER; @@ -579,6 +581,10 @@ private void setRequestMethod(HttpURLConnection uc) throws IOException { } private T parse(Class type, T instance) throws IOException { + return parse(type, instance, 2); + } + + private T parse(Class type, T instance, int timeouts) throws IOException { InputStreamReader r = null; int responseCode = -1; String responseMessage = null; @@ -609,6 +615,10 @@ private T parse(Class type, T instance) throws IOException { // to preserve backward compatibility throw e; } catch (IOException e) { + if (e instanceof SocketTimeoutException && timeouts > 0) { + LOGGER.log(Level.INFO, "timed out accessing " + uc.getURL() + "; will try " + timeouts + " more time(s)", e); + return parse(type, instance, timeouts - 1); + } throw new HttpException(responseCode, responseMessage, uc.getURL(), e); } finally { IOUtils.closeQuietly(r); From 46715cac082163b7e8087c9531e736d69e236e5c Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sun, 2 Jul 2017 17:08:24 -0700 Subject: [PATCH 250/390] [maven-release-plugin] prepare release github-api-1.86 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 1a31c32433..4d623c86fa 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.86-SNAPSHOT + 1.86 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - HEAD + github-api-1.86 From f2fe8eaf86dfa5411fbf57e6981df57244661218 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sun, 2 Jul 2017 17:08:35 -0700 Subject: [PATCH 251/390] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 4d623c86fa..d4cf3f0006 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.86 + 1.87-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - github-api-1.86 + HEAD From b537f9925b8cea4f7736c8f7b80093033c36b795 Mon Sep 17 00:00:00 2001 From: Serban Iordache Date: Fri, 7 Jul 2017 16:21:11 +0200 Subject: [PATCH 252/390] issue #360: Add support for committing multiple files --- .../org/kohsuke/github/GHBlobBuilder.java | 50 ++++++++++ .../org/kohsuke/github/GHCommitBuilder.java | 92 +++++++++++++++++++ .../org/kohsuke/github/GHTreeBuilder.java | 86 +++++++++++++++++ 3 files changed, 228 insertions(+) create mode 100644 src/main/java/org/kohsuke/github/GHBlobBuilder.java create mode 100644 src/main/java/org/kohsuke/github/GHCommitBuilder.java create mode 100644 src/main/java/org/kohsuke/github/GHTreeBuilder.java diff --git a/src/main/java/org/kohsuke/github/GHBlobBuilder.java b/src/main/java/org/kohsuke/github/GHBlobBuilder.java new file mode 100644 index 0000000000..321e88191d --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHBlobBuilder.java @@ -0,0 +1,50 @@ +package org.kohsuke.github; + +import org.apache.commons.codec.binary.Base64; + +import java.io.IOException; + +/** + * Builder pattern for creating a new blob. + * Based on https://developer.github.com/v3/git/blobs/#create-a-blob + */ +public class GHBlobBuilder { + private final GHRepository repo; + private final Requester req; + + public GHBlobBuilder(GHRepository repo) { + this.repo = repo; + req = new Requester(repo.root); + } + + /** + * Configures a blob with the specified text {@code content}. + */ + public GHBlobBuilder textContent(String content) { + req.with("content", content); + req.with("encoding", "utf-8"); + return this; + } + + /** + * Configures a blob with the specified binary {@code content}. + */ + public GHBlobBuilder binaryContent(byte[] content) { + new String(content); + String base64Content = Base64.encodeBase64String(content); + req.with("content", base64Content); + req.with("encoding", "base64"); + return this; + } + + private String getApiTail() { + return String.format("/repos/%s/%s/git/blobs", repo.getOwnerName(), repo.getName()); + } + + /** + * Creates a blob based on the parameters specified thus far. + */ + public GHBlob create() throws IOException { + return req.method("POST").to(getApiTail(), GHBlob.class); + } +} diff --git a/src/main/java/org/kohsuke/github/GHCommitBuilder.java b/src/main/java/org/kohsuke/github/GHCommitBuilder.java new file mode 100644 index 0000000000..5f5b268a63 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHCommitBuilder.java @@ -0,0 +1,92 @@ +package org.kohsuke.github; + +import java.io.IOException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.TimeZone; + +/** + * Builder pattern for creating a new commit. + * Based on https://developer.github.com/v3/git/commits/#create-a-commit + */ +public class GHCommitBuilder { + private final GHRepository repo; + private final Requester req; + + private final List parents = new ArrayList(); + + private static final class UserInfo { + private final String name; + private final String email; + private final String date; + + private UserInfo(String name, String email, Date date) { + this.name = name; + this.email = email; + TimeZone tz = TimeZone.getTimeZone("UTC"); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + df.setTimeZone(tz); + this.date = df.format((date != null) ? date : new Date()); + } + } + + public GHCommitBuilder(GHRepository repo) { + this.repo = repo; + req = new Requester(repo.root); + } + + /** + * @param message the commit message + */ + public GHCommitBuilder message(String message) { + req.with("message", message); + return this; + } + + /** + * @param tree the SHA of the tree object this commit points to + */ + public GHCommitBuilder tree(String tree) { + req.with("tree", tree); + return this; + } + + /** + * @param parent the SHA of a parent commit. + */ + public GHCommitBuilder parent(String parent) { + parents.add(parent); + return this; + } + + /** + * Configures the author of this commit. + */ + public GHCommitBuilder author(String name, String email, Date date) { + req._with("author", new UserInfo(name, email, date)); + return this; + } + + /** + * Configures the committer of this commit. + */ + public GHCommitBuilder committer(String name, String email, Date date) { + req._with("committer", new UserInfo(name, email, date)); + return this; + } + + private String getApiTail() { + return String.format("/repos/%s/%s/git/commits", repo.getOwnerName(), repo.getName()); + } + + /** + * Creates a blob based on the parameters specified thus far. + */ + public GHCommit create() throws IOException { + req._with("parents", parents); + return req.method("POST").to(getApiTail(), GHCommit.class).wrapUp(repo); + } +} diff --git a/src/main/java/org/kohsuke/github/GHTreeBuilder.java b/src/main/java/org/kohsuke/github/GHTreeBuilder.java new file mode 100644 index 0000000000..05c04ef9c1 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHTreeBuilder.java @@ -0,0 +1,86 @@ +package org.kohsuke.github; + +import java.io.IOException; +import java.util.*; + +/** + * Builder pattern for creating a new tree. + * Based on https://developer.github.com/v3/git/trees/#create-a-tree + */ +public class GHTreeBuilder { + private final GHRepository repo; + private final Requester req; + + private final List treeEntries = new ArrayList(); + + private static final class TreeEntry { + private final String path; + private final String mode; + private final String type; + private String sha; + private String content; + + private TreeEntry(String path, String mode, String type) { + this.path = path; + this.mode = mode; + this.type = type; + } + } + + public GHTreeBuilder(GHRepository repo) { + this.repo = repo; + req = new Requester(repo.root); + } + + /** + * @param baseTree the SHA of tree you want to update with new data + */ + public GHTreeBuilder baseTree(String baseTree) { + req.with("base_tree", baseTree); + return this; + } + + /** + * Adds a new entry to the tree. + * Exactly one of the parameters {@code sha} and {@code content} must be non-null. + */ + public GHTreeBuilder entry(String path, String mode, String type, String sha, String content) { + TreeEntry entry = new TreeEntry(path, mode, type); + entry.sha = sha; + entry.content = content; + treeEntries.add(entry); + return this; + } + + /** + * Specialized version of {@link #entry(String, String, String, String, String)} for adding an existing blob referred by its SHA. + */ + public GHTreeBuilder shaEntry(String path, String sha, boolean executable) { + TreeEntry entry = new TreeEntry(path, executable ? "100755" : "100644", "blob"); + entry.sha = sha; + treeEntries.add(entry); + return this; + } + + /** + * Specialized version of {@link #entry(String, String, String, String, String)} for adding a text file with the specified {@code content}. + */ + public GHTreeBuilder textEntry(String path, String content, boolean executable) { + TreeEntry entry = new TreeEntry(path, executable ? "100755" : "100644", "blob"); + entry.content = content; + treeEntries.add(entry); + return this; + } + + private String getApiTail() { + return String.format("/repos/%s/%s/git/trees", repo.getOwnerName(), repo.getName()); + } + + /** + * Creates a tree based on the parameters specified thus far. + */ + public GHTree create() throws IOException { + req._with("tree", treeEntries); + return req.method("POST").to(getApiTail(), GHTree.class).wrap(repo); + } +} From 8d1b44db9781f5a191db534cd1950de7fbd20ed6 Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Mon, 10 Jul 2017 02:39:03 +0300 Subject: [PATCH 253/390] Add ping hook method --- src/main/java/org/kohsuke/github/GHHook.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHHook.java b/src/main/java/org/kohsuke/github/GHHook.java index 73b2eb4364..4aa32e1946 100644 --- a/src/main/java/org/kohsuke/github/GHHook.java +++ b/src/main/java/org/kohsuke/github/GHHook.java @@ -41,6 +41,13 @@ public Map getConfig() { return Collections.unmodifiableMap(config); } + /** + * @see Ping hook + */ + public void ping() throws IOException { + new Requester(getRoot()).method("POST").to(getApiRoute() + "/pings"); + } + /** * Deletes this hook. */ From 4abe87036c2b50c1e27f4ccf27bab4076d2cf03f Mon Sep 17 00:00:00 2001 From: Paulo Miguel Almeida Date: Fri, 14 Jul 2017 04:23:08 +0000 Subject: [PATCH 254/390] Add missing event types used by repository webhooks --- src/main/java/org/kohsuke/github/GHEvent.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHEvent.java b/src/main/java/org/kohsuke/github/GHEvent.java index b33cb991eb..970b6afbf7 100644 --- a/src/main/java/org/kohsuke/github/GHEvent.java +++ b/src/main/java/org/kohsuke/github/GHEvent.java @@ -21,17 +21,30 @@ public enum GHEvent { FORK_APPLY, GIST, GOLLUM, + INSTALLATION, + INSTALLATION_REPOSITORIES, ISSUE_COMMENT, ISSUES, + LABEL, + MARKETPLACE_PURCHASE, MEMBER, + MEMBERSHIP, + MILESTONE, + ORGANIZATION, + ORG_BLOCK, PAGE_BUILD, + PROJECT_CARD, + PROJECT_COLUMN, + PROJECT, PUBLIC, PULL_REQUEST, + PULL_REQUEST_REVIEW, PULL_REQUEST_REVIEW_COMMENT, PUSH, RELEASE, REPOSITORY, // only valid for org hooks STATUS, + TEAM, TEAM_ADD, WATCH, PING, From e90c86ec2fd34c9f8adc91044427298e758d6899 Mon Sep 17 00:00:00 2001 From: Greg Gianforcaro Date: Tue, 18 Jul 2017 11:36:38 -0400 Subject: [PATCH 255/390] Remove Preview status, merge_method is now out of preview --- src/main/java/org/kohsuke/github/GHPullRequest.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index 8b6404a212..096adcf92e 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -23,8 +23,6 @@ */ package org.kohsuke.github; -import static org.kohsuke.github.Previews.POLARIS; - import java.io.IOException; import java.net.URL; import java.util.Collection; @@ -306,10 +304,8 @@ public void merge(String msg, String sha) throws IOException { * @param method * SHA that pull request head must match to allow merge. */ - @Preview @Deprecated public void merge(String msg, MergeMethod method) throws IOException { new Requester(root).method("PUT") - .withPreview(POLARIS) .with("commit_message",msg) .with("merge_method",method) .to(getApiRoute()+"/merge"); From 6dcbace5723bb43a0ebc6f8297fe0b3975e6a150 Mon Sep 17 00:00:00 2001 From: adw1n Date: Tue, 1 Aug 2017 03:38:46 +0200 Subject: [PATCH 256/390] Added getViews method to GHRepository. getViews implements https://developer.github.com/v3/repos/traffic/#views --- .../java/org/kohsuke/github/GHRepository.java | 6 + .../org/kohsuke/github/GHRepositoryViews.java | 57 ++++++++++ .../github/RepositoryTrafficMockTest.java | 107 ++++++++++++++++++ 3 files changed, 170 insertions(+) create mode 100644 src/main/java/org/kohsuke/github/GHRepositoryViews.java create mode 100644 src/test/java/org/kohsuke/github/RepositoryTrafficMockTest.java diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 74fbb4d665..82c9e30d9a 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -1481,6 +1481,12 @@ public GHNotificationStream listNotifications() { return new GHNotificationStream(root,getApiTailUrl("/notifications")); } + /** + * https://developer.github.com/v3/repos/traffic/#views + */ + public GHRepositoryViews getViews() throws IOException{ + return root.retrieve().to(getApiTailUrl("/traffic/views"), GHRepositoryViews.class); + } @Override public int hashCode() { diff --git a/src/main/java/org/kohsuke/github/GHRepositoryViews.java b/src/main/java/org/kohsuke/github/GHRepositoryViews.java new file mode 100644 index 0000000000..8990fb07f4 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHRepositoryViews.java @@ -0,0 +1,57 @@ +package org.kohsuke.github; + +import java.util.List; + +public class GHRepositoryViews{ + private Integer count; + private Integer uniques; + private List views; + + public GHRepositoryViews() { + } + + public GHRepositoryViews(Integer count, Integer uniques, List views) { + this.count = count; + this.uniques = uniques; + this.views = views; + } + + public Integer getCount() { + return count; + } + + public Integer getUniques() { + return uniques; + } + + public List getViews() { + return views; + } + + public static class DayViews { + private String timestamp; + private Integer count; + private Integer uniques; + + public String getTimestamp() { + return timestamp; + } + + public Integer getCount() { + return count; + } + + public Integer getUniques() { + return uniques; + } + + public DayViews() { + } + + public DayViews(String timestamp, Integer count, Integer uniques) { + this.timestamp = timestamp; + this.count = count; + this.uniques = uniques; + } + } +} diff --git a/src/test/java/org/kohsuke/github/RepositoryTrafficMockTest.java b/src/test/java/org/kohsuke/github/RepositoryTrafficMockTest.java new file mode 100644 index 0000000000..2c9ad3ca1e --- /dev/null +++ b/src/test/java/org/kohsuke/github/RepositoryTrafficMockTest.java @@ -0,0 +1,107 @@ +package org.kohsuke.github; + +import org.apache.commons.io.IOUtils; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; + +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Arrays; +import java.util.Iterator; + +public class RepositoryTrafficMockTest { + final private String login = "kohsuke", repositoryName = "github-api"; + private void checkResponse(GHRepositoryViews expected, GHRepositoryViews actual){ + Assert.assertEquals(expected.getCount(), actual.getCount()); + Assert.assertEquals(expected.getUniques(), actual.getUniques()); + Assert.assertEquals(expected.getViews().size(), actual.getViews().size()); + Iterator expectedIt = expected.getViews().iterator(); + Iterator actualIt = actual.getViews().iterator(); + while(expectedIt.hasNext() && actualIt.hasNext()) { + GHRepositoryViews.DayViews expectedDayViews = expectedIt.next(); + GHRepositoryViews.DayViews actualDayViews = actualIt.next(); + Assert.assertEquals(expectedDayViews.getCount(), actualDayViews.getCount()); + Assert.assertEquals(expectedDayViews.getUniques(), actualDayViews.getUniques()); + Assert.assertEquals(expectedDayViews.getTimestamp(), actualDayViews.getTimestamp()); + } + } + + @Test + public void getViews() throws IOException{ + // example taken from the docs https://developer.github.com/v3/repos/traffic/#views + GHRepositoryViews expectedResult = new GHRepositoryViews( + 14850, + 3782, + Arrays.asList( + new GHRepositoryViews.DayViews("2016-10-10T00:00:00Z", 440,143), + new GHRepositoryViews.DayViews("2016-10-11T00:00:00Z", 1308,414), + new GHRepositoryViews.DayViews("2016-10-12T00:00:00Z", 1486,452), + new GHRepositoryViews.DayViews("2016-10-13T00:00:00Z", 1170,401), + new GHRepositoryViews.DayViews("2016-10-14T00:00:00Z", 868,266), + new GHRepositoryViews.DayViews("2016-10-15T00:00:00Z", 495,157), + new GHRepositoryViews.DayViews("2016-10-16T00:00:00Z", 524,175), + new GHRepositoryViews.DayViews("2016-10-17T00:00:00Z", 1263,412), + new GHRepositoryViews.DayViews("2016-10-18T00:00:00Z", 1402,417), + new GHRepositoryViews.DayViews("2016-10-19T00:00:00Z", 1394,424), + new GHRepositoryViews.DayViews("2016-10-20T00:00:00Z", 1492,448), + new GHRepositoryViews.DayViews("2016-10-21T00:00:00Z", 1153,332), + new GHRepositoryViews.DayViews("2016-10-22T00:00:00Z", 566,168), + new GHRepositoryViews.DayViews("2016-10-23T00:00:00Z", 675,184), + new GHRepositoryViews.DayViews("2016-10-24T00:00:00Z", 614,237) + ) + ); + String mockedGHRepositoryViewsResponse = GitHub.MAPPER.writeValueAsString(expectedResult); + + GitHub gitHub = GitHub.connect(login, null); + GitHub gitHubSpy = Mockito.spy(gitHub); + GHRepository repo = gitHubSpy.getUser(login).getRepository(repositoryName); + + + // accessing traffic info requires push access to the repo + // since we don't have that, let the mocking begin... + + HttpConnector connectorSpy = Mockito.spy(gitHubSpy.getConnector()); + Mockito.doReturn(connectorSpy).when(gitHubSpy).getConnector(); + + + // also known as the "uc" in the Requester class + HttpURLConnection mockHttpURLConnection = Mockito.mock(HttpURLConnection.class); + + + // needed for Requester.setRequestMethod + Mockito.doReturn("GET").when(mockHttpURLConnection).getRequestMethod(); + + + // this covers calls on "uc" in Requester.setupConnection and Requester.buildRequest + URL trafficURL = new URL("https://api.github.com/repos/"+login+"/"+repositoryName+"/traffic/views"); + Mockito.doReturn(mockHttpURLConnection).when(connectorSpy).connect(Mockito.eq(trafficURL)); + + + // make Requester.parse work + Mockito.doReturn(200).when(mockHttpURLConnection).getResponseCode(); + Mockito.doReturn("OK").when(mockHttpURLConnection).getResponseMessage(); + InputStream stubInputStream = IOUtils.toInputStream(mockedGHRepositoryViewsResponse, "UTF-8"); + Mockito.doReturn(stubInputStream).when(mockHttpURLConnection).getInputStream(); + + + GHRepositoryViews views = repo.getViews(); + + + checkResponse(expectedResult, views); + } + + @Test + public void getViewsAccessFailureDueToInsufficientPermissions() throws IOException { + GitHub gitHub = GitHub.connect(login, null); + GHRepository repo = gitHub.getUser(login).getRepository(repositoryName); + try { + repo.getViews(); + Assert.fail("Exception should be thrown, since we don't have permission to access repo's traffic info."); + } + catch (HttpException ex){ + } + } +} From 8accf07d4620d0d2ef0b2c0f1f8ce86303d8e929 Mon Sep 17 00:00:00 2001 From: adw1n Date: Tue, 1 Aug 2017 04:02:10 +0200 Subject: [PATCH 257/390] Changed timestamp (GHRepositoryViews.DayViews.timestamp) field type from String to Date. --- .../java/org/kohsuke/github/GHRepositoryViews.java | 11 +++++++++-- .../org/kohsuke/github/RepositoryTrafficMockTest.java | 9 ++++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHRepositoryViews.java b/src/main/java/org/kohsuke/github/GHRepositoryViews.java index 8990fb07f4..1e7a627b0e 100644 --- a/src/main/java/org/kohsuke/github/GHRepositoryViews.java +++ b/src/main/java/org/kohsuke/github/GHRepositoryViews.java @@ -1,5 +1,6 @@ package org.kohsuke.github; +import java.util.Date; import java.util.List; public class GHRepositoryViews{ @@ -29,11 +30,11 @@ public List getViews() { } public static class DayViews { - private String timestamp; + private Date timestamp; private Integer count; private Integer uniques; - public String getTimestamp() { + public Date getTimestamp() { return timestamp; } @@ -49,6 +50,12 @@ public DayViews() { } public DayViews(String timestamp, Integer count, Integer uniques) { + this.timestamp = GitHub.parseDate(timestamp); + this.count = count; + this.uniques = uniques; + } + + public DayViews(Date timestamp, Integer count, Integer uniques) { this.timestamp = timestamp; this.count = count; this.uniques = uniques; diff --git a/src/test/java/org/kohsuke/github/RepositoryTrafficMockTest.java b/src/test/java/org/kohsuke/github/RepositoryTrafficMockTest.java index 2c9ad3ca1e..ecd944d35f 100644 --- a/src/test/java/org/kohsuke/github/RepositoryTrafficMockTest.java +++ b/src/test/java/org/kohsuke/github/RepositoryTrafficMockTest.java @@ -1,5 +1,6 @@ package org.kohsuke.github; +import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.io.IOUtils; import org.junit.Assert; import org.junit.Test; @@ -9,8 +10,10 @@ import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; +import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Iterator; +import java.util.TimeZone; public class RepositoryTrafficMockTest { final private String login = "kohsuke", repositoryName = "github-api"; @@ -53,7 +56,11 @@ public void getViews() throws IOException{ new GHRepositoryViews.DayViews("2016-10-24T00:00:00Z", 614,237) ) ); - String mockedGHRepositoryViewsResponse = GitHub.MAPPER.writeValueAsString(expectedResult); + SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); + ObjectMapper mapper = new ObjectMapper().setDateFormat(dateFormat); + String mockedGHRepositoryViewsResponse = mapper.writeValueAsString(expectedResult); + GitHub gitHub = GitHub.connect(login, null); GitHub gitHubSpy = Mockito.spy(gitHub); From a1819bf23265fdb2f3dd0768d61ee3a9feb58d7f Mon Sep 17 00:00:00 2001 From: adw1n Date: Tue, 1 Aug 2017 06:20:24 +0200 Subject: [PATCH 258/390] Added getClones method to GHRepository (https://developer.github.com/v3/repos/traffic/#clones). --- .../java/org/kohsuke/github/GHRepository.java | 7 + .../kohsuke/github/GHRepositoryClones.java | 33 ++++ .../github/GHRepositoryTrafficInfo.java | 57 ++++++ .../org/kohsuke/github/GHRepositoryViews.java | 41 +--- .../github/RepositoryTrafficMockTest.java | 114 ------------ .../kohsuke/github/RepositoryTrafficTest.java | 175 ++++++++++++++++++ 6 files changed, 277 insertions(+), 150 deletions(-) create mode 100644 src/main/java/org/kohsuke/github/GHRepositoryClones.java create mode 100644 src/main/java/org/kohsuke/github/GHRepositoryTrafficInfo.java delete mode 100644 src/test/java/org/kohsuke/github/RepositoryTrafficMockTest.java create mode 100644 src/test/java/org/kohsuke/github/RepositoryTrafficTest.java diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 82c9e30d9a..bf2a669ff1 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -1488,6 +1488,13 @@ public GHRepositoryViews getViews() throws IOException{ return root.retrieve().to(getApiTailUrl("/traffic/views"), GHRepositoryViews.class); } + /** + * https://developer.github.com/v3/repos/traffic/#clones + */ + public GHRepositoryClones getClones() throws IOException{ + return root.retrieve().to(getApiTailUrl("/traffic/clones"), GHRepositoryClones.class); + } + @Override public int hashCode() { return ("Repository:"+getOwnerName()+":"+name).hashCode(); diff --git a/src/main/java/org/kohsuke/github/GHRepositoryClones.java b/src/main/java/org/kohsuke/github/GHRepositoryClones.java new file mode 100644 index 0000000000..e88a902a7e --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHRepositoryClones.java @@ -0,0 +1,33 @@ +package org.kohsuke.github; + +import java.util.Date; +import java.util.List; + +public class GHRepositoryClones extends GHRepositoryTrafficInfo { + private List clones; + + public GHRepositoryClones() { + } + + public GHRepositoryClones(Integer count, Integer uniques, List clones) { + super(count, uniques); + this.clones = clones; + } + + public List getClones() { + return clones; + } + + public static class DayClones extends GHRepositoryTrafficInfo.DayInfo { + public DayClones() { + } + + public DayClones(String timestamp, Integer count, Integer uniques) { + super(timestamp, count, uniques); + } + + public DayClones(Date timestamp, Integer count, Integer uniques) { + super(timestamp, count, uniques); + } + } +} diff --git a/src/main/java/org/kohsuke/github/GHRepositoryTrafficInfo.java b/src/main/java/org/kohsuke/github/GHRepositoryTrafficInfo.java new file mode 100644 index 0000000000..143ed23a02 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHRepositoryTrafficInfo.java @@ -0,0 +1,57 @@ +package org.kohsuke.github; + +import java.util.Date; + +public abstract class GHRepositoryTrafficInfo { + private Integer count; + private Integer uniques; + + public GHRepositoryTrafficInfo() { + } + + public GHRepositoryTrafficInfo(Integer count, Integer uniques) { + this.count = count; + this.uniques = uniques; + } + + public Integer getCount() { + return count; + } + + public Integer getUniques() { + return uniques; + } + + public static abstract class DayInfo { + private Date timestamp; + private Integer count; + private Integer uniques; + + public Date getTimestamp() { + return timestamp; + } + + public Integer getCount() { + return count; + } + + public Integer getUniques() { + return uniques; + } + + public DayInfo() { + } + + public DayInfo(String timestamp, Integer count, Integer uniques) { + this.timestamp = GitHub.parseDate(timestamp); + this.count = count; + this.uniques = uniques; + } + + public DayInfo(Date timestamp, Integer count, Integer uniques) { + this.timestamp = timestamp; + this.count = count; + this.uniques = uniques; + } + } +} diff --git a/src/main/java/org/kohsuke/github/GHRepositoryViews.java b/src/main/java/org/kohsuke/github/GHRepositoryViews.java index 1e7a627b0e..0d6d9d8493 100644 --- a/src/main/java/org/kohsuke/github/GHRepositoryViews.java +++ b/src/main/java/org/kohsuke/github/GHRepositoryViews.java @@ -3,62 +3,31 @@ import java.util.Date; import java.util.List; -public class GHRepositoryViews{ - private Integer count; - private Integer uniques; +public class GHRepositoryViews extends GHRepositoryTrafficInfo { private List views; public GHRepositoryViews() { } public GHRepositoryViews(Integer count, Integer uniques, List views) { - this.count = count; - this.uniques = uniques; + super(count, uniques); this.views = views; } - public Integer getCount() { - return count; - } - - public Integer getUniques() { - return uniques; - } - public List getViews() { return views; } - public static class DayViews { - private Date timestamp; - private Integer count; - private Integer uniques; - - public Date getTimestamp() { - return timestamp; - } - - public Integer getCount() { - return count; - } - - public Integer getUniques() { - return uniques; - } - + public static class DayViews extends GHRepositoryTrafficInfo.DayInfo { public DayViews() { } public DayViews(String timestamp, Integer count, Integer uniques) { - this.timestamp = GitHub.parseDate(timestamp); - this.count = count; - this.uniques = uniques; + super(timestamp, count, uniques); } public DayViews(Date timestamp, Integer count, Integer uniques) { - this.timestamp = timestamp; - this.count = count; - this.uniques = uniques; + super(timestamp, count, uniques); } } } diff --git a/src/test/java/org/kohsuke/github/RepositoryTrafficMockTest.java b/src/test/java/org/kohsuke/github/RepositoryTrafficMockTest.java deleted file mode 100644 index ecd944d35f..0000000000 --- a/src/test/java/org/kohsuke/github/RepositoryTrafficMockTest.java +++ /dev/null @@ -1,114 +0,0 @@ -package org.kohsuke.github; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.apache.commons.io.IOUtils; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.URL; -import java.text.SimpleDateFormat; -import java.util.Arrays; -import java.util.Iterator; -import java.util.TimeZone; - -public class RepositoryTrafficMockTest { - final private String login = "kohsuke", repositoryName = "github-api"; - private void checkResponse(GHRepositoryViews expected, GHRepositoryViews actual){ - Assert.assertEquals(expected.getCount(), actual.getCount()); - Assert.assertEquals(expected.getUniques(), actual.getUniques()); - Assert.assertEquals(expected.getViews().size(), actual.getViews().size()); - Iterator expectedIt = expected.getViews().iterator(); - Iterator actualIt = actual.getViews().iterator(); - while(expectedIt.hasNext() && actualIt.hasNext()) { - GHRepositoryViews.DayViews expectedDayViews = expectedIt.next(); - GHRepositoryViews.DayViews actualDayViews = actualIt.next(); - Assert.assertEquals(expectedDayViews.getCount(), actualDayViews.getCount()); - Assert.assertEquals(expectedDayViews.getUniques(), actualDayViews.getUniques()); - Assert.assertEquals(expectedDayViews.getTimestamp(), actualDayViews.getTimestamp()); - } - } - - @Test - public void getViews() throws IOException{ - // example taken from the docs https://developer.github.com/v3/repos/traffic/#views - GHRepositoryViews expectedResult = new GHRepositoryViews( - 14850, - 3782, - Arrays.asList( - new GHRepositoryViews.DayViews("2016-10-10T00:00:00Z", 440,143), - new GHRepositoryViews.DayViews("2016-10-11T00:00:00Z", 1308,414), - new GHRepositoryViews.DayViews("2016-10-12T00:00:00Z", 1486,452), - new GHRepositoryViews.DayViews("2016-10-13T00:00:00Z", 1170,401), - new GHRepositoryViews.DayViews("2016-10-14T00:00:00Z", 868,266), - new GHRepositoryViews.DayViews("2016-10-15T00:00:00Z", 495,157), - new GHRepositoryViews.DayViews("2016-10-16T00:00:00Z", 524,175), - new GHRepositoryViews.DayViews("2016-10-17T00:00:00Z", 1263,412), - new GHRepositoryViews.DayViews("2016-10-18T00:00:00Z", 1402,417), - new GHRepositoryViews.DayViews("2016-10-19T00:00:00Z", 1394,424), - new GHRepositoryViews.DayViews("2016-10-20T00:00:00Z", 1492,448), - new GHRepositoryViews.DayViews("2016-10-21T00:00:00Z", 1153,332), - new GHRepositoryViews.DayViews("2016-10-22T00:00:00Z", 566,168), - new GHRepositoryViews.DayViews("2016-10-23T00:00:00Z", 675,184), - new GHRepositoryViews.DayViews("2016-10-24T00:00:00Z", 614,237) - ) - ); - SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); - dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); - ObjectMapper mapper = new ObjectMapper().setDateFormat(dateFormat); - String mockedGHRepositoryViewsResponse = mapper.writeValueAsString(expectedResult); - - - GitHub gitHub = GitHub.connect(login, null); - GitHub gitHubSpy = Mockito.spy(gitHub); - GHRepository repo = gitHubSpy.getUser(login).getRepository(repositoryName); - - - // accessing traffic info requires push access to the repo - // since we don't have that, let the mocking begin... - - HttpConnector connectorSpy = Mockito.spy(gitHubSpy.getConnector()); - Mockito.doReturn(connectorSpy).when(gitHubSpy).getConnector(); - - - // also known as the "uc" in the Requester class - HttpURLConnection mockHttpURLConnection = Mockito.mock(HttpURLConnection.class); - - - // needed for Requester.setRequestMethod - Mockito.doReturn("GET").when(mockHttpURLConnection).getRequestMethod(); - - - // this covers calls on "uc" in Requester.setupConnection and Requester.buildRequest - URL trafficURL = new URL("https://api.github.com/repos/"+login+"/"+repositoryName+"/traffic/views"); - Mockito.doReturn(mockHttpURLConnection).when(connectorSpy).connect(Mockito.eq(trafficURL)); - - - // make Requester.parse work - Mockito.doReturn(200).when(mockHttpURLConnection).getResponseCode(); - Mockito.doReturn("OK").when(mockHttpURLConnection).getResponseMessage(); - InputStream stubInputStream = IOUtils.toInputStream(mockedGHRepositoryViewsResponse, "UTF-8"); - Mockito.doReturn(stubInputStream).when(mockHttpURLConnection).getInputStream(); - - - GHRepositoryViews views = repo.getViews(); - - - checkResponse(expectedResult, views); - } - - @Test - public void getViewsAccessFailureDueToInsufficientPermissions() throws IOException { - GitHub gitHub = GitHub.connect(login, null); - GHRepository repo = gitHub.getUser(login).getRepository(repositoryName); - try { - repo.getViews(); - Assert.fail("Exception should be thrown, since we don't have permission to access repo's traffic info."); - } - catch (HttpException ex){ - } - } -} diff --git a/src/test/java/org/kohsuke/github/RepositoryTrafficTest.java b/src/test/java/org/kohsuke/github/RepositoryTrafficTest.java new file mode 100644 index 0000000000..27e3915bd2 --- /dev/null +++ b/src/test/java/org/kohsuke/github/RepositoryTrafficTest.java @@ -0,0 +1,175 @@ +package org.kohsuke.github; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.io.IOUtils; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; + +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.TimeZone; + +public class RepositoryTrafficTest { + final private String login = "kohsuke", repositoryName = "github-api"; + + @SuppressWarnings("unchecked") + private void checkResponse(T expected, T actual){ + Assert.assertEquals(expected.getCount(), actual.getCount()); + Assert.assertEquals(expected.getUniques(), actual.getUniques()); + + List expectedList = null; + List actualList = null; + Iterator expectedIt; + Iterator actualIt; + + if(expected instanceof GHRepositoryViews){ + expectedList = (List)((List)((GHRepositoryViews) expected).getViews()); + actualList = (List)((List)((GHRepositoryViews) actual).getViews()); + } + else if(expected instanceof GHRepositoryClones){ + expectedList = (List)((List)((GHRepositoryClones) expected).getClones()); + actualList = (List)((List)((GHRepositoryClones) actual).getClones()); + } + + Assert.assertEquals(expectedList.size(), actualList.size()); + expectedIt = expectedList.iterator(); + actualIt = actualList.iterator(); + + while(expectedIt.hasNext() && actualIt.hasNext()) { + T.DayInfo expectedDayInfo = expectedIt.next(); + T.DayInfo actualDayInfo = actualIt.next(); + Assert.assertEquals(expectedDayInfo.getCount(), actualDayInfo.getCount()); + Assert.assertEquals(expectedDayInfo.getUniques(), actualDayInfo.getUniques()); + Assert.assertEquals(expectedDayInfo.getTimestamp(), actualDayInfo.getTimestamp()); + } + } + + private void testTraffic(T expectedResult) throws IOException{ + SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); + ObjectMapper mapper = new ObjectMapper().setDateFormat(dateFormat); + String mockedResponse = mapper.writeValueAsString(expectedResult); + + + GitHub gitHub = GitHub.connect(login, null); + GitHub gitHubSpy = Mockito.spy(gitHub); + GHRepository repo = gitHubSpy.getUser(login).getRepository(repositoryName); + + + // accessing traffic info requires push access to the repo + // since we don't have that, let the mocking begin... + + HttpConnector connectorSpy = Mockito.spy(gitHubSpy.getConnector()); + Mockito.doReturn(connectorSpy).when(gitHubSpy).getConnector(); + + + // also known as the "uc" in the Requester class + HttpURLConnection mockHttpURLConnection = Mockito.mock(HttpURLConnection.class); + + + // needed for Requester.setRequestMethod + Mockito.doReturn("GET").when(mockHttpURLConnection).getRequestMethod(); + + + // this covers calls on "uc" in Requester.setupConnection and Requester.buildRequest + URL trafficURL = new URL( + "https://api.github.com/repos/"+login+"/"+repositoryName+"/traffic/" + + ((expectedResult instanceof GHRepositoryViews) ? "views" : "clones") + ); + Mockito.doReturn(mockHttpURLConnection).when(connectorSpy).connect(Mockito.eq(trafficURL)); + + + // make Requester.parse work + Mockito.doReturn(200).when(mockHttpURLConnection).getResponseCode(); + Mockito.doReturn("OK").when(mockHttpURLConnection).getResponseMessage(); + InputStream stubInputStream = IOUtils.toInputStream(mockedResponse, "UTF-8"); + Mockito.doReturn(stubInputStream).when(mockHttpURLConnection).getInputStream(); + + if(expectedResult instanceof GHRepositoryViews){ + GHRepositoryViews views = repo.getViews(); + checkResponse(expectedResult, views); + } + else if(expectedResult instanceof GHRepositoryClones) { + GHRepositoryClones clones = repo.getClones(); + checkResponse(expectedResult, clones); + } + } + + @Test + public void testGetViews() throws IOException{ + GHRepositoryViews expectedResult = new GHRepositoryViews( + 21523359, + 65534, + Arrays.asList( + new GHRepositoryViews.DayViews("2016-10-10T00:00:00Z", 3, 2), + new GHRepositoryViews.DayViews("2016-10-11T00:00:00Z", 9, 4), + new GHRepositoryViews.DayViews("2016-10-12T00:00:00Z", 27, 8), + new GHRepositoryViews.DayViews("2016-10-13T00:00:00Z", 81, 16), + new GHRepositoryViews.DayViews("2016-10-14T00:00:00Z", 243, 32), + new GHRepositoryViews.DayViews("2016-10-15T00:00:00Z", 729, 64), + new GHRepositoryViews.DayViews("2016-10-16T00:00:00Z", 2187, 128), + new GHRepositoryViews.DayViews("2016-10-17T00:00:00Z", 6561, 256), + new GHRepositoryViews.DayViews("2016-10-18T00:00:00Z", 19683, 512), + new GHRepositoryViews.DayViews("2016-10-19T00:00:00Z", 59049, 1024), + new GHRepositoryViews.DayViews("2016-10-20T00:00:00Z", 177147, 2048), + new GHRepositoryViews.DayViews("2016-10-21T00:00:00Z", 531441, 4096), + new GHRepositoryViews.DayViews("2016-10-22T00:00:00Z", 1594323, 8192), + new GHRepositoryViews.DayViews("2016-10-23T00:00:00Z", 4782969, 16384), + new GHRepositoryViews.DayViews("2016-10-24T00:00:00Z", 14348907, 32768) + ) + ); + testTraffic(expectedResult); + } + + @Test + public void testGetClones() throws IOException{ + GHRepositoryClones expectedResult = new GHRepositoryClones( + 1500, + 455, + Arrays.asList( + new GHRepositoryClones.DayClones("2016-10-10T00:00:00Z", 10,3), + new GHRepositoryClones.DayClones("2016-10-11T00:00:00Z", 20,6), + new GHRepositoryClones.DayClones("2016-10-12T00:00:00Z", 30,5), + new GHRepositoryClones.DayClones("2016-10-13T00:00:00Z", 40,7), + new GHRepositoryClones.DayClones("2016-10-14T00:00:00Z", 50,11), + new GHRepositoryClones.DayClones("2016-10-15T00:00:00Z", 60,12), + new GHRepositoryClones.DayClones("2016-10-16T00:00:00Z", 70,19), + new GHRepositoryClones.DayClones("2016-10-17T00:00:00Z", 170,111), + new GHRepositoryClones.DayClones("2016-10-18T00:00:00Z", 180,70), + new GHRepositoryClones.DayClones("2016-10-19T00:00:00Z", 190,10), + new GHRepositoryClones.DayClones("2016-10-20T00:00:00Z", 200,18), + new GHRepositoryClones.DayClones("2016-10-21T00:00:00Z", 210,8), + new GHRepositoryClones.DayClones("2016-10-22T00:00:00Z", 220,168), + new GHRepositoryClones.DayClones("2016-10-23T00:00:00Z", 5,2), + new GHRepositoryClones.DayClones("2016-10-24T00:00:00Z", 45,5) + ) + ); + testTraffic(expectedResult); + } + + @Test + public void testGetTrafficStatsAccessFailureDueToInsufficientPermissions() throws IOException { + String errorMsg = "Exception should be thrown, since we don't have permission to access repo traffic info."; + GitHub gitHub = GitHub.connect(login, null); + GHRepository repo = gitHub.getUser(login).getRepository(repositoryName); + try { + repo.getViews(); + Assert.fail(errorMsg); + } + catch (HttpException ex){ + } + try { + repo.getClones(); + Assert.fail(errorMsg); + } + catch (HttpException ex){ + } + } +} From 7396395f9076e133c42129febd32981c0364445c Mon Sep 17 00:00:00 2001 From: Jae Gangemi Date: Tue, 8 Aug 2017 14:31:11 -0600 Subject: [PATCH 259/390] - updated ignore entries for eclipse/moc os --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index cb9b4d6a4a..3c2c3c6427 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,7 @@ target *.iml *.ipr *.iws +.classpath +.project +.settings/ +.DS_Store From 23cd51a6dac951870c7ebd43a4a491d55e1872b8 Mon Sep 17 00:00:00 2001 From: Jae Gangemi Date: Tue, 8 Aug 2017 14:31:41 -0600 Subject: [PATCH 260/390] - improved branch protection support --- .../org/kohsuke/github/BranchProtection.java | 21 -- .../java/org/kohsuke/github/GHBranch.java | 38 ++-- .../kohsuke/github/GHBranchProtection.java | 152 ++++++++++++++ .../github/GHBranchProtectionBuilder.java | 186 ++++++++++++++++++ .../java/org/kohsuke/github/GHRepository.java | 16 +- .../java/org/kohsuke/github/Requester.java | 7 +- .../github/GHBranchProtectionTest.java | 78 ++++++++ .../github/GHContentIntegrationTest.java | 7 - 8 files changed, 441 insertions(+), 64 deletions(-) delete mode 100644 src/main/java/org/kohsuke/github/BranchProtection.java create mode 100644 src/main/java/org/kohsuke/github/GHBranchProtection.java create mode 100644 src/main/java/org/kohsuke/github/GHBranchProtectionBuilder.java create mode 100644 src/test/java/org/kohsuke/github/GHBranchProtectionTest.java diff --git a/src/main/java/org/kohsuke/github/BranchProtection.java b/src/main/java/org/kohsuke/github/BranchProtection.java deleted file mode 100644 index 4ae03b162a..0000000000 --- a/src/main/java/org/kohsuke/github/BranchProtection.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.kohsuke.github; - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author Kohsuke Kawaguchi - * @see GHBranch#disableProtection() - */ -@SuppressFBWarnings(value = {"UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD", "URF_UNREAD_FIELD"}, justification = "JSON API") -class BranchProtection { - boolean enabled; - RequiredStatusChecks requiredStatusChecks; - - static class RequiredStatusChecks { - EnforcementLevel enforcement_level; - List contexts = new ArrayList(); - } -} diff --git a/src/main/java/org/kohsuke/github/GHBranch.java b/src/main/java/org/kohsuke/github/GHBranch.java index f54bea9f47..bdfe118993 100644 --- a/src/main/java/org/kohsuke/github/GHBranch.java +++ b/src/main/java/org/kohsuke/github/GHBranch.java @@ -4,10 +4,6 @@ import java.io.IOException; import java.net.URL; -import java.util.Arrays; -import java.util.Collection; - -import org.kohsuke.github.BranchProtection.RequiredStatusChecks; import com.fasterxml.jackson.annotation.JsonProperty; @@ -15,10 +11,10 @@ /** * A branch in a repository. - * + * * @author Yusuke Kokubo */ -@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", +@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD", "URF_UNREAD_FIELD"}, justification = "JSON API") public class GHBranch { private GitHub root; @@ -33,7 +29,7 @@ public class GHBranch { public static class Commit { String sha; - + @SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now") String url; } @@ -69,6 +65,10 @@ public URL getProtectionUrl() { return GitHub.parseURL(protection_url); } + @Preview @Deprecated + public GHBranchProtection getProtection() throws IOException { + return root.retrieve().withPreview(LOKI).to(protection_url, GHBranchProtection.class); + } /** * The commit that this branch currently points to. @@ -82,9 +82,7 @@ public String getSHA1() { */ @Preview @Deprecated public void disableProtection() throws IOException { - BranchProtection bp = new BranchProtection(); - bp.enabled = false; - setProtection(bp); + new Requester(root).method("DELETE").withPreview(LOKI).to(protection_url); } /** @@ -93,28 +91,14 @@ public void disableProtection() throws IOException { * @see GHCommitStatus#getContext() */ @Preview @Deprecated - public void enableProtection(EnforcementLevel level, Collection contexts) throws IOException { - BranchProtection bp = new BranchProtection(); - bp.enabled = true; - bp.requiredStatusChecks = new RequiredStatusChecks(); - bp.requiredStatusChecks.enforcement_level = level; - bp.requiredStatusChecks.contexts.addAll(contexts); - setProtection(bp); - } - - @Preview @Deprecated - public void enableProtection(EnforcementLevel level, String... contexts) throws IOException { - enableProtection(level, Arrays.asList(contexts)); - } - - private void setProtection(BranchProtection bp) throws IOException { - new Requester(root).method("PATCH").withPreview(LOKI)._with("protection",bp).to(getApiRoute()); + public GHBranchProtectionBuilder enableProtection() { + return new GHBranchProtectionBuilder(this); } String getApiRoute() { return owner.getApiTailUrl("/branches/"+name); } - + @Override public String toString() { final String url = owner != null ? owner.getUrl().toString() : "unknown"; diff --git a/src/main/java/org/kohsuke/github/GHBranchProtection.java b/src/main/java/org/kohsuke/github/GHBranchProtection.java new file mode 100644 index 0000000000..3216366115 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHBranchProtection.java @@ -0,0 +1,152 @@ +package org.kohsuke.github; + +import java.util.Collection; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + +@SuppressFBWarnings(value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD", + "URF_UNREAD_FIELD" }, justification = "JSON API") +public class GHBranchProtection { + @JsonProperty("enforce_admins") + private EnforceAdmins enforceAdmins; + + @JsonProperty("required_pull_request_reviews") + private RequiredReviews requiredReviews; + + @JsonProperty("required_status_checks") + private RequiredStatusChecks requiredStatusChecks; + + @JsonProperty + private Restrictions restrictions; + + @JsonProperty + private String url; + + public EnforceAdmins getEnforceAdmins() { + return enforceAdmins; + } + + public RequiredReviews getRequiredReviews() { + return requiredReviews; + } + + public RequiredStatusChecks getRequiredStatusChecks() { + return requiredStatusChecks; + } + + public Restrictions getRestrictions() { + return restrictions; + } + + public String getUrl() { + return url; + } + + public static class EnforceAdmins { + @JsonProperty + private boolean enabled; + + @JsonProperty + private String url; + + public String getUrl() { + return url; + } + + public boolean isEnabled() { + return enabled; + } + } + + public static class RequiredReviews { + @JsonProperty("dismissal_restrictions") + private Restrictions dismissalRestriction; + + @JsonProperty("dismiss_stale_reviews") + private boolean dismissStaleReviews; + + @JsonProperty("require_code_owner_reviews") + private boolean requireCodeOwnerReviews; + + @JsonProperty + private String url; + + public Restrictions getDismissalRestrictions() { + return dismissalRestriction; + } + + public String getUrl() { + return url; + } + + public boolean isDismissStaleReviews() { + return dismissStaleReviews; + } + + public boolean isRequireCodeOwnerReviews() { + return requireCodeOwnerReviews; + } + } + + public static class RequiredStatusChecks { + @JsonProperty + private Collection contexts; + + @JsonProperty + private boolean strict; + + @JsonProperty + private String url; + + public Collection getContexts() { + return contexts; + } + + public String getUrl() { + return url; + } + + public boolean isRequiresBranchUpToDate() { + return strict; + } + } + + public static class Restrictions { + @JsonProperty + private Collection teams; + + @JsonProperty("teams_url") + private String teamsUrl; + + @JsonProperty + private String url; + + @JsonProperty + private Collection users; + + @JsonProperty("users_url") + private String usersUrl; + + public Collection getTeams() { + return teams; + } + + public String getTeamsUrl() { + return teamsUrl; + } + + public String getUrl() { + return url; + } + + public Collection getUsers() { + return users; + } + + public String getUsersUrl() { + return usersUrl; + } + } +} diff --git a/src/main/java/org/kohsuke/github/GHBranchProtectionBuilder.java b/src/main/java/org/kohsuke/github/GHBranchProtectionBuilder.java new file mode 100644 index 0000000000..fc521fff39 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHBranchProtectionBuilder.java @@ -0,0 +1,186 @@ +package org.kohsuke.github; + +import static org.kohsuke.github.Previews.LOKI; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + +@SuppressFBWarnings(value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD", + "URF_UNREAD_FIELD" }, justification = "JSON API") +public class GHBranchProtectionBuilder { + private final GHBranch branch; + + private boolean enforceAdmins; + private Map prReviews; + private Restrictions restrictions; + private StatusChecks statusChecks; + + GHBranchProtectionBuilder(GHBranch branch) { + this.branch = branch; + } + + public GHBranchProtectionBuilder addRequiredChecks(Collection checks) { + getStatusChecks().contexts.addAll(checks); + return this; + } + + public GHBranchProtectionBuilder addRequiredChecks(String... checks) { + addRequiredChecks(Arrays.asList(checks)); + return this; + } + + public GHBranchProtectionBuilder dismissStaleReviews() { + getPrReviews().put("dismiss_stale_reviews", true); + return this; + } + + public GHBranchProtection enable() throws IOException { + return requester().method("PUT") + .withNullable("required_status_checks", statusChecks) + .withNullable("required_pull_request_reviews", prReviews) + .withNullable("restrictions", restrictions) + .withNullable("enforce_admins", enforceAdmins) + .to(branch.getProtectionUrl().toString(), GHBranchProtection.class); + } + + public GHBranchProtectionBuilder includeAdmins() { + enforceAdmins = true; + return this; + } + + public GHBranchProtectionBuilder requireBranchIsUpToDate() { + getStatusChecks().strict = true; + return this; + } + + public GHBranchProtectionBuilder requireCodeOwnReviews() { + getPrReviews().put("require_code_owner_reviews", true); + return this; + } + + public GHBranchProtectionBuilder requireReviews() { + getPrReviews(); + return this; + } + + public GHBranchProtectionBuilder restrictPushAccess() { + getRestrictions(); + return this; + } + + public GHBranchProtectionBuilder teamPushAccess(Collection teams) { + for (GHTeam team : teams) { + teamPushAccess(team); + } + return this; + } + + public GHBranchProtectionBuilder teamPushAccess(GHTeam... teams) { + for (GHTeam team : teams) { + getRestrictions().teams.add(team.getSlug()); + } + return this; + } + + public GHBranchProtectionBuilder teamReviewDismissals(Collection teams) { + for (GHTeam team : teams) { + teamReviewDismissals(team); + } + return this; + } + + public GHBranchProtectionBuilder teamReviewDismissals(GHTeam... teams) { + for (GHTeam team : teams) { + addReviewRestriction(team.getSlug(), true); + } + return this; + } + + public GHBranchProtectionBuilder userPushAccess(Collection users) { + for (GHUser user : users) { + userPushAccess(user); + } + return this; + } + + public GHBranchProtectionBuilder userPushAccess(GHUser... users) { + for (GHUser user : users) { + getRestrictions().users.add(user.getLogin()); + } + return this; + } + + public GHBranchProtectionBuilder userReviewDismissals(Collection users) { + for (GHUser team : users) { + userReviewDismissals(team); + } + return this; + } + + public GHBranchProtectionBuilder userReviewDismissals(GHUser... users) { + for (GHUser user : users) { + addReviewRestriction(user.getLogin(), false); + } + return this; + } + + private void addReviewRestriction(String restriction, boolean isTeam) { + getPrReviews(); + + if (!prReviews.containsKey("dismissal_restrictions")) { + prReviews.put("dismissal_restrictions", new Restrictions()); + } + + Restrictions restrictions = (Restrictions) prReviews.get("dismissal_restrictions"); + + if (isTeam) { + restrictions.teams.add(restriction); + } else { + restrictions.users.add(restriction); + } + } + + private Map getPrReviews() { + if (prReviews == null) { + prReviews = new HashMap(); + } + return prReviews; + } + + private Restrictions getRestrictions() { + if (restrictions == null) { + restrictions = new Restrictions(); + } + return restrictions; + } + + private StatusChecks getStatusChecks() { + if (statusChecks == null) { + statusChecks = new StatusChecks(); + } + return statusChecks; + } + + private Requester requester() { + return new Requester(branch.getRoot()).withPreview(LOKI); + } + + private static class Restrictions { + private Set teams = new HashSet(); + private Set users = new HashSet(); + } + + private static class StatusChecks { + final List contexts = new ArrayList(); + boolean strict; + } +} diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 74fbb4d665..5c8b09c098 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -60,7 +60,7 @@ * @author Kohsuke Kawaguchi */ @SuppressWarnings({"UnusedDeclaration"}) -@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", +@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; @@ -434,8 +434,8 @@ public String getMasterBranch() { public int getSize() { return size; } - - + + /** * Gets the collaborators on this repository. * This set always appear to include the owner. @@ -1146,7 +1146,7 @@ public GHHook createWebHook(URL url) throws IOException { * @deprecated * Use {@link #getHooks()} and {@link #createHook(String, Map, Collection, boolean)} */ - @SuppressFBWarnings(value = "DMI_COLLECTION_OF_URLS", + @SuppressFBWarnings(value = "DMI_COLLECTION_OF_URLS", justification = "It causes a performance degradation, but we have already exposed it to the API") public Set getPostCommitHooks() { return postCommitHooks; @@ -1155,7 +1155,7 @@ public Set getPostCommitHooks() { /** * Live set view of the post-commit hook. */ - @SuppressFBWarnings(value = "DMI_COLLECTION_OF_URLS", + @SuppressFBWarnings(value = "DMI_COLLECTION_OF_URLS", justification = "It causes a performance degradation, but we have already exposed it to the API") @SkipFromToString private final Set postCommitHooks = new AbstractSet() { @@ -1223,7 +1223,7 @@ public boolean remove(Object url) { */ public Map getBranches() throws IOException { Map r = new TreeMap(); - for (GHBranch p : root.retrieve().to(getApiTailUrl("branches"), GHBranch[].class)) { + for (GHBranch p : root.retrieve().withPreview(LOKI).to(getApiTailUrl("branches"), GHBranch[].class)) { p.wrap(this); r.put(p.getName(),p); } @@ -1231,7 +1231,7 @@ public Map getBranches() throws IOException { } public GHBranch getBranch(String name) throws IOException { - return root.retrieve().to(getApiTailUrl("branches/"+name),GHBranch.class).wrap(this); + return root.retrieve().withPreview(LOKI).to(getApiTailUrl("branches/"+name),GHBranch.class).wrap(this); } /** @@ -1453,7 +1453,7 @@ public int hashCode() { public boolean equals(Object obj) { // We ignore contributions in the calculation return super.equals(obj); - } + } } /** diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index d7d6239190..576d313f5d 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -170,6 +170,11 @@ public Requester with(@WillClose/*later*/ InputStream body) { return this; } + public Requester withNullable(String key, Object value) { + args.add(new Entry(key, value)); + return this; + } + public Requester _with(String key, Object value) { if (value!=null) { args.add(new Entry(key,value)); @@ -314,7 +319,7 @@ public InputStream asStream(String tailApiUrl) throws IOException { setupConnection(root.getApiURL(tailApiUrl)); buildRequest(); - + try { return wrapStream(uc.getInputStream()); } catch (IOException e) { diff --git a/src/test/java/org/kohsuke/github/GHBranchProtectionTest.java b/src/test/java/org/kohsuke/github/GHBranchProtectionTest.java new file mode 100644 index 0000000000..a6a8a831cd --- /dev/null +++ b/src/test/java/org/kohsuke/github/GHBranchProtectionTest.java @@ -0,0 +1,78 @@ +package org.kohsuke.github; + +import org.junit.Before; +import org.junit.Test; +import org.kohsuke.github.GHBranchProtection.EnforceAdmins; +import org.kohsuke.github.GHBranchProtection.RequiredReviews; +import org.kohsuke.github.GHBranchProtection.RequiredStatusChecks; + +public class GHBranchProtectionTest extends AbstractGitHubApiTestBase { + private static final String BRANCH = "bp-test"; + private static final String BRANCH_REF = "heads/" + BRANCH; + + private GHBranch branch; + + private GHRepository repo; + + @Before + @Override + public void setUp() throws Exception { + super.setUp(); + + repo = gitHub.getRepository("github-api-test-org/GHContentIntegrationTest").fork(); + + if (repo.getRef(BRANCH_REF) == null) { + repo.createRef("refs/" + BRANCH_REF, repo.getBranch("master").getSHA1()); + } + + branch = repo.getBranch(BRANCH); + + if (branch.isProtected()) { + branch.disableProtection(); + } + + branch = repo.getBranch(BRANCH); + assertFalse(branch.isProtected()); + } + + @Test + public void testEnableBranchProtections() throws Exception { + // team/user restrictions require an organization repo to test against + GHBranchProtection protection = branch.enableProtection() + .addRequiredChecks("test-status-check") + .requireBranchIsUpToDate() + .requireCodeOwnReviews() + .dismissStaleReviews() + .includeAdmins() + .enable(); + + RequiredStatusChecks statusChecks = protection.getRequiredStatusChecks(); + assertNotNull(statusChecks); + assertTrue(statusChecks.isRequiresBranchUpToDate()); + assertTrue(statusChecks.getContexts().contains("test-status-check")); + + RequiredReviews requiredReviews = protection.getRequiredReviews(); + assertNotNull(requiredReviews); + assertTrue(requiredReviews.isDismissStaleReviews()); + assertTrue(requiredReviews.isRequireCodeOwnerReviews()); + + EnforceAdmins enforceAdmins = protection.getEnforceAdmins(); + assertNotNull(enforceAdmins); + assertTrue(enforceAdmins.isEnabled()); + } + + @Test + public void testEnableProtectionOnly() throws Exception { + branch.enableProtection().enable(); + assertTrue(repo.getBranch(BRANCH).isProtected()); + } + + @Test + public void testEnableRequireReviewsOnly() throws Exception { + GHBranchProtection protection = branch.enableProtection() + .requireReviews() + .enable(); + + assertNotNull(protection.getRequiredReviews()); + } +} diff --git a/src/test/java/org/kohsuke/github/GHContentIntegrationTest.java b/src/test/java/org/kohsuke/github/GHContentIntegrationTest.java index c642d662e7..8e3873708b 100644 --- a/src/test/java/org/kohsuke/github/GHContentIntegrationTest.java +++ b/src/test/java/org/kohsuke/github/GHContentIntegrationTest.java @@ -20,13 +20,6 @@ public void setUp() throws Exception { repo = gitHub.getRepository("github-api-test-org/GHContentIntegrationTest").fork(); } - @Test - public void testBranchProtection() throws Exception { - GHBranch b = repo.getBranch("master"); - b.enableProtection(EnforcementLevel.NON_ADMINS, "foo/bar"); - b.disableProtection(); - } - @Test public void testGetFileContent() throws Exception { GHContent content = repo.getFileContent("ghcontent-ro/a-file-with-content"); From f2a2ad90b7a8ed334444c7523f829b9892d440c1 Mon Sep 17 00:00:00 2001 From: Matt Mitchell Date: Tue, 29 Aug 2017 11:30:25 -0700 Subject: [PATCH 261/390] Switch to a concurrent hash map --- .../org/kohsuke/github/GHCommitStatus.java | 1 + src/main/java/org/kohsuke/github/GitHub.java | 69 ++++++------------- 2 files changed, 23 insertions(+), 47 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHCommitStatus.java b/src/main/java/org/kohsuke/github/GHCommitStatus.java index 241f8b98b4..f71be99622 100644 --- a/src/main/java/org/kohsuke/github/GHCommitStatus.java +++ b/src/main/java/org/kohsuke/github/GHCommitStatus.java @@ -1,5 +1,6 @@ package org.kohsuke.github; +import java.io.IOException; import java.net.URL; /** diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index f787a2db45..bde74b1262 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -47,6 +47,7 @@ import java.util.Map; import java.util.Set; import java.util.TimeZone; +import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Logger; import javax.annotation.CheckForNull; import javax.annotation.Nonnull; @@ -147,8 +148,8 @@ public class GitHub { } } - users = new Hashtable(); - orgs = new Hashtable(); + users = new ConcurrentHashMap(); + orgs = new ConcurrentHashMap(); this.rateLimitHandler = rateLimitHandler; this.abuseLimitHandler = abuseLimitHandler; @@ -360,12 +361,6 @@ public GHRateLimit rateLimit() throws IOException { @WithBridgeMethods(GHUser.class) public GHMyself getMyself() throws IOException { requireCredential(); - - // This entire block is under synchronization to avoid the relatively common case - // where a bunch of threads try to enter this code simultaneously. While we could - // scope the synchronization separately around the map retrieval and update (or use a concurrent hash) - // map, the point is to avoid making unnecessary GH API calls, which are expensive from - // an API rate standpoint synchronized (this) { if (this.myself != null) return myself; @@ -381,20 +376,13 @@ public GHMyself getMyself() throws IOException { * Obtains the object that represents the named user. */ public GHUser getUser(String login) throws IOException { - // This entire block is under synchronization to avoid the relatively common case - // where a bunch of threads try to enter this code simultaneously. While we could - // scope the synchronization separately around the map retrieval and update (or use a concurrent hash - // map), the point is to avoid making unnecessary GH API calls, which are expensive from - // an API rate standpoint - synchronized (users) { - 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; + 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; } @@ -402,43 +390,30 @@ public GHUser getUser(String login) throws IOException { * clears all cached data in order for external changes (modifications and del */ public void refreshCache() { - synchronized (users) { - users.clear(); - } - synchronized (orgs) { - orgs.clear(); - } + users.clear(); + orgs.clear(); } /** * Interns the given {@link GHUser}. */ protected GHUser getUser(GHUser orig) { - synchronized (users) { - GHUser u = users.get(orig.getLogin()); - if (u==null) { - orig.root = this; - users.put(orig.getLogin(),orig); - return orig; - } - return u; + GHUser u = users.get(orig.getLogin()); + if (u==null) { + orig.root = this; + users.put(orig.getLogin(),orig); + return orig; } + return u; } public GHOrganization getOrganization(String name) throws IOException { - // This entire block is under synchronization to avoid the relatively common case - // where a bunch of threads try to enter this code simultaneously. While we could - // scope the synchronization separately around the map retrieval and update (or use a concurrent hash - // map), the point is to avoid making unnecessary GH API calls, which are expensive from - // an API rate standpoint - synchronized (orgs) { - GHOrganization o = orgs.get(name); - if (o==null) { - o = retrieve().to("/orgs/" + name, GHOrganization.class).wrapUp(this); - orgs.put(name,o); - } - return o; + GHOrganization o = orgs.get(name); + if (o==null) { + o = retrieve().to("/orgs/" + name, GHOrganization.class).wrapUp(this); + orgs.put(name,o); } + return o; } /** From 9dabec107ba0e69282d6eb9312d9a0c1bcc7f000 Mon Sep 17 00:00:00 2001 From: Stephen Connolly Date: Fri, 1 Sep 2017 12:52:15 +0100 Subject: [PATCH 262/390] Add basic support for tag objects --- .../java/org/kohsuke/github/GHRepository.java | 53 ++++++++++++++++ .../java/org/kohsuke/github/GHTagObject.java | 60 +++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 src/main/java/org/kohsuke/github/GHTagObject.java diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 74fbb4d665..09caa9210d 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -784,6 +784,26 @@ public GHRef[] getRefs() throws IOException { return GHRef.wrap(root.retrieve().to(String.format("/repos/%s/%s/git/refs", getOwnerName(), name), GHRef[].class), root); } + + /** + * Retrieves all refs for the github repository. + * + * @return paged iterable of all refs + * @throws IOException on failure communicating with GitHub, potentially due to an invalid ref type being requested + */ + public PagedIterable listRefs() throws IOException { + final String url = String.format("/repos/%s/%s/git/refs", getOwnerName(), name); + return new PagedIterable() { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator(url, GHRef[].class, pageSize)) { + protected void wrapUp(GHRef[] page) { + // no-op + } + }; + } + }; + } + /** * Retrieves all refs of the given type for the current GitHub repository. * @param refType the type of reg to search for e.g. tags or commits @@ -793,6 +813,27 @@ public GHRef[] getRefs() throws IOException { public GHRef[] getRefs(String refType) throws IOException { return GHRef.wrap(root.retrieve().to(String.format("/repos/%s/%s/git/refs/%s", getOwnerName(), name, refType), GHRef[].class),root); } + + /** + * Retrieves all refs of the given type for the current GitHub repository. + * + * @param refType the type of reg to search for e.g. tags or commits + * @return paged iterable of all refs of the specified type + * @throws IOException on failure communicating with GitHub, potentially due to an invalid ref type being requested + */ + public PagedIterable listRefs(String refType) throws IOException { + final String url = String.format("/repos/%s/%s/git/refs/%s", getOwnerName(), name, refType); + return new PagedIterable() { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator(url, GHRef[].class, pageSize)) { + protected void wrapUp(GHRef[] page) { + // no-op + } + }; + } + }; + } + /** * Retrive a ref of the given type for the current GitHub repository. * @@ -810,6 +851,18 @@ public GHRef getRef(String refName) throws IOException { refName = refName.replaceAll("#", "%23"); return root.retrieve().to(String.format("/repos/%s/%s/git/refs/%s", getOwnerName(), name, refName), GHRef.class).wrap(root); } + + /** + * Returns the annotated tag object. Only valid if the {@link GHRef#getObject()} has a + * {@link GHRef.GHObject#getType()} of {@code tag}. + * + * @param sha the sha of the tag object + * @return the annotated tag object + */ + public GHTagObject getTagObject(String sha) throws IOException { + return root.retrieve().to(getApiTailUrl("git/tags/" + sha), GHTagObject.class).wrap(this); + } + /** * Retrive a tree of the given type for the current GitHub repository. * diff --git a/src/main/java/org/kohsuke/github/GHTagObject.java b/src/main/java/org/kohsuke/github/GHTagObject.java new file mode 100644 index 0000000000..a95571c479 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHTagObject.java @@ -0,0 +1,60 @@ +package org.kohsuke.github; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + +/** + * Represents an annotated tag in a {@link GHRepository} + * + * @see GHRepository#getAnnotatedTag() + */ +@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", + "NP_UNWRITTEN_FIELD"}, justification = "JSON API") +public class GHTagObject { + private GHRepository owner; + private GitHub root; + + private String tag; + private String sha; + private String url; + private String message; + private GitUser tagger; + private GHRef.GHObject object; + + /*package*/ GHTagObject wrap(GHRepository owner) { + this.owner = owner; + this.root = owner.root; + return this; + } + + public GHRepository getOwner() { + return owner; + } + + public GitHub getRoot() { + return root; + } + + public String getTag() { + return tag; + } + + public String getSha() { + return sha; + } + + public String getUrl() { + return url; + } + + public String getMessage() { + return message; + } + + public GitUser getTagger() { + return tagger; + } + + public GHRef.GHObject getObject() { + return object; + } +} From 2f8c3997f7834249eb748e0e84ea7b734406dfa2 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 8 Sep 2017 14:13:21 -0700 Subject: [PATCH 263/390] Restored signature of the previous enableProtection() method --- .../org/kohsuke/github/EnforcementLevel.java | 3 +++ .../java/org/kohsuke/github/GHBranch.java | 18 +++++++++++++ .../github/GHBranchProtectionBuilder.java | 25 ++++++++++++++++--- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/kohsuke/github/EnforcementLevel.java b/src/main/java/org/kohsuke/github/EnforcementLevel.java index 1b29195299..81c86428c4 100644 --- a/src/main/java/org/kohsuke/github/EnforcementLevel.java +++ b/src/main/java/org/kohsuke/github/EnforcementLevel.java @@ -3,8 +3,11 @@ import java.util.Locale; /** + * This was added during preview API period but it has changed since then. + * * @author Kohsuke Kawaguchi */ +@Deprecated public enum EnforcementLevel { OFF, NON_ADMINS, EVERYONE; diff --git a/src/main/java/org/kohsuke/github/GHBranch.java b/src/main/java/org/kohsuke/github/GHBranch.java index bdfe118993..c2e5b29441 100644 --- a/src/main/java/org/kohsuke/github/GHBranch.java +++ b/src/main/java/org/kohsuke/github/GHBranch.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.net.URL; +import java.util.Collection; import com.fasterxml.jackson.annotation.JsonProperty; @@ -95,6 +96,23 @@ public GHBranchProtectionBuilder enableProtection() { return new GHBranchProtectionBuilder(this); } + // backward compatibility with previous signature + @Deprecated + public void enableProtection(EnforcementLevel level, Collection contexts) throws IOException { + switch (level) { + case OFF: + disableProtection(); + break; + case NON_ADMINS: + case EVERYONE: + enableProtection() + .addRequiredChecks(contexts) + .includeAdmins(level==EnforcementLevel.EVERYONE) + .enable(); + break; + } + } + String getApiRoute() { return owner.getApiTailUrl("/branches/"+name); } diff --git a/src/main/java/org/kohsuke/github/GHBranchProtectionBuilder.java b/src/main/java/org/kohsuke/github/GHBranchProtectionBuilder.java index fc521fff39..5fccf7eb8c 100644 --- a/src/main/java/org/kohsuke/github/GHBranchProtectionBuilder.java +++ b/src/main/java/org/kohsuke/github/GHBranchProtectionBuilder.java @@ -14,6 +14,11 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +/** + * Builder to configure the branch protection settings. + * + * @see GHBranch#enableProtection() + */ @SuppressFBWarnings(value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD", "URF_UNREAD_FIELD" }, justification = "JSON API") public class GHBranchProtectionBuilder { @@ -53,17 +58,29 @@ public GHBranchProtection enable() throws IOException { } public GHBranchProtectionBuilder includeAdmins() { - enforceAdmins = true; + return includeAdmins(true); + } + + public GHBranchProtectionBuilder includeAdmins(boolean v) { + enforceAdmins = v; return this; } - + public GHBranchProtectionBuilder requireBranchIsUpToDate() { - getStatusChecks().strict = true; + return requireBranchIsUpToDate(true); + } + + public GHBranchProtectionBuilder requireBranchIsUpToDate(boolean v) { + getStatusChecks().strict = v; return this; } public GHBranchProtectionBuilder requireCodeOwnReviews() { - getPrReviews().put("require_code_owner_reviews", true); + return requireCodeOwnReviews(true); + } + + public GHBranchProtectionBuilder requireCodeOwnReviews(boolean v) { + getPrReviews().put("require_code_owner_reviews", v); return this; } From cda27d5963ab06c92d6c210fe43d25ac54081587 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 8 Sep 2017 14:16:09 -0700 Subject: [PATCH 264/390] This field should be still final --- src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java | 3 +-- src/main/java/org/kohsuke/github/GHQueryBuilder.java | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java b/src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java index 1385b0c67e..65136dc0a4 100644 --- a/src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java +++ b/src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java @@ -1,7 +1,6 @@ package org.kohsuke.github; import java.io.IOException; -import java.util.Locale; import org.apache.commons.lang.StringUtils; @@ -15,7 +14,7 @@ public class GHCommitSearchBuilder extends GHSearchBuilder { /*package*/ GHCommitSearchBuilder(GitHub root) { super(root,CommitSearchResult.class); - req = req.withPreview(Previews.CLOAK); + req.withPreview(Previews.CLOAK); } /** diff --git a/src/main/java/org/kohsuke/github/GHQueryBuilder.java b/src/main/java/org/kohsuke/github/GHQueryBuilder.java index 5eca4278a1..bb85fbbe95 100644 --- a/src/main/java/org/kohsuke/github/GHQueryBuilder.java +++ b/src/main/java/org/kohsuke/github/GHQueryBuilder.java @@ -7,7 +7,7 @@ */ public abstract class GHQueryBuilder { protected final GitHub root; - protected Requester req; + protected final Requester req; /*package*/ GHQueryBuilder(GitHub root) { this.root = root; From 8dd6dbf995226b6b0c950246f9beb1792553d4fc Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 8 Sep 2017 15:52:11 -0700 Subject: [PATCH 265/390] getRef never returns null --- .../java/org/kohsuke/github/GHBranchProtectionTest.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/test/java/org/kohsuke/github/GHBranchProtectionTest.java b/src/test/java/org/kohsuke/github/GHBranchProtectionTest.java index a6a8a831cd..b7ae713d87 100644 --- a/src/test/java/org/kohsuke/github/GHBranchProtectionTest.java +++ b/src/test/java/org/kohsuke/github/GHBranchProtectionTest.java @@ -6,6 +6,8 @@ import org.kohsuke.github.GHBranchProtection.RequiredReviews; import org.kohsuke.github.GHBranchProtection.RequiredStatusChecks; +import java.io.FileNotFoundException; + public class GHBranchProtectionTest extends AbstractGitHubApiTestBase { private static final String BRANCH = "bp-test"; private static final String BRANCH_REF = "heads/" + BRANCH; @@ -21,7 +23,9 @@ public void setUp() throws Exception { repo = gitHub.getRepository("github-api-test-org/GHContentIntegrationTest").fork(); - if (repo.getRef(BRANCH_REF) == null) { + try { + repo.getRef(BRANCH_REF); + } catch (FileNotFoundException e) { repo.createRef("refs/" + BRANCH_REF, repo.getBranch("master").getSHA1()); } From df9faf494385f80ab818da3004e48534727e6167 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 8 Sep 2017 16:09:41 -0700 Subject: [PATCH 266/390] Auto-retry flaky tests --- pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pom.xml b/pom.xml index d4cf3f0006..351b8a405b 100644 --- a/pom.xml +++ b/pom.xml @@ -34,6 +34,12 @@ + + maven-surefire-plugin + + 2 + + org.codehaus.mojo animal-sniffer-maven-plugin From aebbe86cfcee9c1d5c8fee9f83b40773d886f84c Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 07:57:49 -0700 Subject: [PATCH 267/390] Keeping findbugs happy --- src/main/java/org/kohsuke/github/GHPullRequest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index 3e25daeb81..d297fe822f 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -297,9 +297,9 @@ public GHPullRequestReview createReview(String body, @CheckForNull GHPullRequest public GHPullRequestReview createReview(String body, @CheckForNull GHPullRequestReviewState event, List comments) throws IOException { - if (event == null) { - event = GHPullRequestReviewState.PENDING; - } +// if (event == null) { +// event = GHPullRequestReviewState.PENDING; +// } List draftComments = new ArrayList(comments.size()); for (GHPullRequestReviewComment c : comments) { draftComments.add(new DraftReviewComment(c.getBody(), c.getPath(), c.getPosition())); From ad28ca4a9053275afc45860130dca4c8df764210 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 07:59:31 -0700 Subject: [PATCH 268/390] Use string constant like other previews --- src/main/java/org/kohsuke/github/GHPullRequest.java | 6 ++++-- src/main/java/org/kohsuke/github/GHPullRequestReview.java | 8 +++++--- src/main/java/org/kohsuke/github/Previews.java | 1 + 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index d297fe822f..078603d6fa 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -32,6 +32,8 @@ import java.util.List; import javax.annotation.CheckForNull; +import static org.kohsuke.github.Previews.BLACK_CAT; + /** * A pull request. * @@ -234,7 +236,7 @@ public PagedIterable listReviews() { return new PagedIterable() { public PagedIterator _iterator(int pageSize) { return new PagedIterator(root.retrieve() - .withPreview("application/vnd.github.black-cat-preview+json") + .withPreview(BLACK_CAT) .asIterator(String.format("%s/reviews", getApiRoute()), GHPullRequestReview[].class, pageSize)) { @Override @@ -308,7 +310,7 @@ public GHPullRequestReview createReview(String body, @CheckForNull GHPullRequest .with("body", body) //.with("event", event.name()) ._with("comments", draftComments) - .withPreview("application/vnd.github.black-cat-preview+json") + .withPreview(BLACK_CAT) .to(getApiRoute() + "/reviews", GHPullRequestReview.class).wrapUp(this); } diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReview.java b/src/main/java/org/kohsuke/github/GHPullRequestReview.java index 1fb57d4bf9..b25f28b59a 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestReview.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestReview.java @@ -26,6 +26,8 @@ import java.io.IOException; import java.net.URL; +import static org.kohsuke.github.Previews.BLACK_CAT; + /** * Review to the pull request * @@ -105,7 +107,7 @@ public void submit(String body, GHPullRequestReviewState event) throws IOExcepti @Deprecated public void delete() throws IOException { new Requester(owner.root).method("DELETE") - .withPreview("application/vnd.github.black-cat-preview+json") + .withPreview(BLACK_CAT) .to(getApiRoute()); } @@ -117,7 +119,7 @@ public void delete() throws IOException { public void dismiss(String message) throws IOException { new Requester(owner.root).method("PUT") .with("message", message) - .withPreview("application/vnd.github.black-cat-preview+json") + .withPreview(BLACK_CAT) .to(getApiRoute()+"/dismissals"); state = GHPullRequestReviewState.DISMISSED; } @@ -132,7 +134,7 @@ public PagedIterable listReviewComments() throws IOE public PagedIterator _iterator(int pageSize) { return new PagedIterator( owner.root.retrieve() - .withPreview("application/vnd.github.black-cat-preview+json") + .withPreview(BLACK_CAT) .asIterator(getApiRoute() + "/comments", GHPullRequestReviewComment[].class, pageSize)) { protected void wrapUp(GHPullRequestReviewComment[] page) { diff --git a/src/main/java/org/kohsuke/github/Previews.java b/src/main/java/org/kohsuke/github/Previews.java index 3f98c3d4b9..2bc6dccbc8 100644 --- a/src/main/java/org/kohsuke/github/Previews.java +++ b/src/main/java/org/kohsuke/github/Previews.java @@ -8,4 +8,5 @@ static final String DRAX = "application/vnd.github.drax-preview+json"; static final String SQUIRREL_GIRL = "application/vnd.github.squirrel-girl-preview"; static final String CLOAK = "application/vnd.github.cloak-preview"; + static final String BLACK_CAT = "application/vnd.github.black-cat-preview+json"; } From 336924ef23f0928d6c9c388c1bb6104ad86874f0 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 08:06:18 -0700 Subject: [PATCH 269/390] [maven-release-plugin] prepare release github-api-1.87 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 351b8a405b..7e204af06d 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.87-SNAPSHOT + 1.87 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - HEAD + github-api-1.87 From b0c51e03b74ac112aa89ffa4465b3695656c8508 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 08:06:27 -0700 Subject: [PATCH 270/390] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 7e204af06d..d509a2488b 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.87 + 1.88-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - github-api-1.87 + HEAD From ea8df9bd610f3fe081a12e82168b2d28812d211c Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 08:13:51 -0700 Subject: [PATCH 271/390] javadoc fix --- src/main/java/org/kohsuke/github/GHTagObject.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHTagObject.java b/src/main/java/org/kohsuke/github/GHTagObject.java index a95571c479..0e3acdeaa7 100644 --- a/src/main/java/org/kohsuke/github/GHTagObject.java +++ b/src/main/java/org/kohsuke/github/GHTagObject.java @@ -5,7 +5,7 @@ /** * Represents an annotated tag in a {@link GHRepository} * - * @see GHRepository#getAnnotatedTag() + * @see GHRepository#getTagObject(String) */ @SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD"}, justification = "JSON API") From 5ed8a3456684f14a185afb7b6ae2005a1295a094 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 08:19:20 -0700 Subject: [PATCH 272/390] [maven-release-plugin] prepare release github-api-1.88 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index d509a2488b..733dd51a97 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.88-SNAPSHOT + 1.88 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - HEAD + github-api-1.88 From 57c36f437a7187769ecc2a9847a2f36b963ba401 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 08:19:29 -0700 Subject: [PATCH 273/390] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 733dd51a97..9b11b977f3 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.88 + 1.89-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - github-api-1.88 + HEAD From 9af8112148fec83e706aca83afd8a9d5c734f0e5 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 11:37:18 -0700 Subject: [PATCH 274/390] Tightening up access control and use primitive type --- .../kohsuke/github/GHRepositoryClones.java | 19 ++++++++---- .../github/GHRepositoryTrafficInfo.java | 29 ++++++++++--------- .../org/kohsuke/github/GHRepositoryViews.java | 19 ++++++++---- .../kohsuke/github/RepositoryTrafficTest.java | 22 +++++--------- 4 files changed, 51 insertions(+), 38 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHRepositoryClones.java b/src/main/java/org/kohsuke/github/GHRepositoryClones.java index e88a902a7e..1bd126038a 100644 --- a/src/main/java/org/kohsuke/github/GHRepositoryClones.java +++ b/src/main/java/org/kohsuke/github/GHRepositoryClones.java @@ -3,13 +3,18 @@ import java.util.Date; import java.util.List; +/** + * Repository clone statistics. + * + * @see GHRepository#getClones() + */ public class GHRepositoryClones extends GHRepositoryTrafficInfo { private List clones; - public GHRepositoryClones() { + /*package*/ GHRepositoryClones() { } - public GHRepositoryClones(Integer count, Integer uniques, List clones) { + /*package*/ GHRepositoryClones(Integer count, Integer uniques, List clones) { super(count, uniques); this.clones = clones; } @@ -18,15 +23,19 @@ public List getClones() { return clones; } + public List getDailyInfo() { + return getClones(); + } + public static class DayClones extends GHRepositoryTrafficInfo.DayInfo { - public DayClones() { + /*package*/ DayClones() { } - public DayClones(String timestamp, Integer count, Integer uniques) { + /*package*/ DayClones(String timestamp, int count, int uniques) { super(timestamp, count, uniques); } - public DayClones(Date timestamp, Integer count, Integer uniques) { + /*package*/ DayClones(Date timestamp, int count, int uniques) { super(timestamp, count, uniques); } } diff --git a/src/main/java/org/kohsuke/github/GHRepositoryTrafficInfo.java b/src/main/java/org/kohsuke/github/GHRepositoryTrafficInfo.java index 143ed23a02..24bd177bd2 100644 --- a/src/main/java/org/kohsuke/github/GHRepositoryTrafficInfo.java +++ b/src/main/java/org/kohsuke/github/GHRepositoryTrafficInfo.java @@ -1,54 +1,57 @@ package org.kohsuke.github; import java.util.Date; +import java.util.List; public abstract class GHRepositoryTrafficInfo { - private Integer count; - private Integer uniques; + private int count; + private int uniques; - public GHRepositoryTrafficInfo() { + /*package*/ GHRepositoryTrafficInfo() { } - public GHRepositoryTrafficInfo(Integer count, Integer uniques) { + /*package*/ GHRepositoryTrafficInfo(int count, int uniques) { this.count = count; this.uniques = uniques; } - public Integer getCount() { + public int getCount() { return count; } - public Integer getUniques() { + public int getUniques() { return uniques; } + public abstract List getDailyInfo(); + public static abstract class DayInfo { private Date timestamp; - private Integer count; - private Integer uniques; + private int count; + private int uniques; public Date getTimestamp() { return timestamp; } - public Integer getCount() { + public int getCount() { return count; } - public Integer getUniques() { + public int getUniques() { return uniques; } - public DayInfo() { + /*package*/ DayInfo() { } - public DayInfo(String timestamp, Integer count, Integer uniques) { + /*package*/ DayInfo(String timestamp, Integer count, Integer uniques) { this.timestamp = GitHub.parseDate(timestamp); this.count = count; this.uniques = uniques; } - public DayInfo(Date timestamp, Integer count, Integer uniques) { + /*package*/ DayInfo(Date timestamp, Integer count, Integer uniques) { this.timestamp = timestamp; this.count = count; this.uniques = uniques; diff --git a/src/main/java/org/kohsuke/github/GHRepositoryViews.java b/src/main/java/org/kohsuke/github/GHRepositoryViews.java index 0d6d9d8493..2f7ea80f78 100644 --- a/src/main/java/org/kohsuke/github/GHRepositoryViews.java +++ b/src/main/java/org/kohsuke/github/GHRepositoryViews.java @@ -3,13 +3,18 @@ import java.util.Date; import java.util.List; +/** + * Repository view statistics. + * + * @see GHRepository#getViews() + */ public class GHRepositoryViews extends GHRepositoryTrafficInfo { private List views; - public GHRepositoryViews() { + /*package*/ GHRepositoryViews() { } - public GHRepositoryViews(Integer count, Integer uniques, List views) { + /*package*/ GHRepositoryViews(int count, int uniques, List views) { super(count, uniques); this.views = views; } @@ -18,15 +23,19 @@ public List getViews() { return views; } + public List getDailyInfo() { + return getViews(); + } + public static class DayViews extends GHRepositoryTrafficInfo.DayInfo { - public DayViews() { + /*package*/ DayViews() { } - public DayViews(String timestamp, Integer count, Integer uniques) { + /*package*/ DayViews(String timestamp, int count, int uniques) { super(timestamp, count, uniques); } - public DayViews(Date timestamp, Integer count, Integer uniques) { + /*package*/ DayViews(Date timestamp, int count, int uniques) { super(timestamp, count, uniques); } } diff --git a/src/test/java/org/kohsuke/github/RepositoryTrafficTest.java b/src/test/java/org/kohsuke/github/RepositoryTrafficTest.java index 27e3915bd2..66cccd7ed3 100644 --- a/src/test/java/org/kohsuke/github/RepositoryTrafficTest.java +++ b/src/test/java/org/kohsuke/github/RepositoryTrafficTest.java @@ -4,6 +4,7 @@ import org.apache.commons.io.IOUtils; import org.junit.Assert; import org.junit.Test; +import org.kohsuke.github.GHRepositoryTrafficInfo.DayInfo; import org.mockito.Mockito; import java.io.IOException; @@ -24,27 +25,18 @@ private void checkResponse(T expected, T act Assert.assertEquals(expected.getCount(), actual.getCount()); Assert.assertEquals(expected.getUniques(), actual.getUniques()); - List expectedList = null; - List actualList = null; - Iterator expectedIt; - Iterator actualIt; - - if(expected instanceof GHRepositoryViews){ - expectedList = (List)((List)((GHRepositoryViews) expected).getViews()); - actualList = (List)((List)((GHRepositoryViews) actual).getViews()); - } - else if(expected instanceof GHRepositoryClones){ - expectedList = (List)((List)((GHRepositoryClones) expected).getClones()); - actualList = (List)((List)((GHRepositoryClones) actual).getClones()); - } + List expectedList = expected.getDailyInfo(); + List actualList = actual.getDailyInfo(); + Iterator expectedIt; + Iterator actualIt; Assert.assertEquals(expectedList.size(), actualList.size()); expectedIt = expectedList.iterator(); actualIt = actualList.iterator(); while(expectedIt.hasNext() && actualIt.hasNext()) { - T.DayInfo expectedDayInfo = expectedIt.next(); - T.DayInfo actualDayInfo = actualIt.next(); + DayInfo expectedDayInfo = expectedIt.next(); + DayInfo actualDayInfo = actualIt.next(); Assert.assertEquals(expectedDayInfo.getCount(), actualDayInfo.getCount()); Assert.assertEquals(expectedDayInfo.getUniques(), actualDayInfo.getUniques()); Assert.assertEquals(expectedDayInfo.getTimestamp(), actualDayInfo.getTimestamp()); From 2c80ef178d7e73ec717442942a151a5569fe05d8 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 11:39:12 -0700 Subject: [PATCH 275/390] Capture commonality between total and daily --- .../kohsuke/github/GHRepositoryTrafficInfo.java | 4 ++-- .../java/org/kohsuke/github/TrafficInfo.java | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 src/main/java/org/kohsuke/github/TrafficInfo.java diff --git a/src/main/java/org/kohsuke/github/GHRepositoryTrafficInfo.java b/src/main/java/org/kohsuke/github/GHRepositoryTrafficInfo.java index 24bd177bd2..7336c93285 100644 --- a/src/main/java/org/kohsuke/github/GHRepositoryTrafficInfo.java +++ b/src/main/java/org/kohsuke/github/GHRepositoryTrafficInfo.java @@ -3,7 +3,7 @@ import java.util.Date; import java.util.List; -public abstract class GHRepositoryTrafficInfo { +public abstract class GHRepositoryTrafficInfo implements TrafficInfo { private int count; private int uniques; @@ -25,7 +25,7 @@ public int getUniques() { public abstract List getDailyInfo(); - public static abstract class DayInfo { + public static abstract class DayInfo implements TrafficInfo { private Date timestamp; private int count; private int uniques; diff --git a/src/main/java/org/kohsuke/github/TrafficInfo.java b/src/main/java/org/kohsuke/github/TrafficInfo.java new file mode 100644 index 0000000000..9b232e9f1a --- /dev/null +++ b/src/main/java/org/kohsuke/github/TrafficInfo.java @@ -0,0 +1,16 @@ +package org.kohsuke.github; + +/** + * @author Kohsuke Kawaguchi + */ +public interface TrafficInfo { + /** + * Total count of hits. + */ + int getCount(); + + /** + * Unique visitors. + */ + int getUniques(); +} From fb4706721518e47aa29fde685276d1d2509bbf2a Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 11:40:28 -0700 Subject: [PATCH 276/390] Naming changes to emphasize that these are just traffic info --- .../java/org/kohsuke/github/GHRepository.java | 8 +- .../github/GHRepositoryCloneTraffic.java | 42 +++++++++ .../kohsuke/github/GHRepositoryClones.java | 42 --------- .../github/GHRepositoryViewTraffic.java | 42 +++++++++ .../org/kohsuke/github/GHRepositoryViews.java | 42 --------- .../kohsuke/github/RepositoryTrafficTest.java | 93 ++++++++++--------- 6 files changed, 135 insertions(+), 134 deletions(-) create mode 100644 src/main/java/org/kohsuke/github/GHRepositoryCloneTraffic.java delete mode 100644 src/main/java/org/kohsuke/github/GHRepositoryClones.java create mode 100644 src/main/java/org/kohsuke/github/GHRepositoryViewTraffic.java delete mode 100644 src/main/java/org/kohsuke/github/GHRepositoryViews.java diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index bf2a669ff1..2c71592321 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -1484,15 +1484,15 @@ public GHNotificationStream listNotifications() { /** * https://developer.github.com/v3/repos/traffic/#views */ - public GHRepositoryViews getViews() throws IOException{ - return root.retrieve().to(getApiTailUrl("/traffic/views"), GHRepositoryViews.class); + public GHRepositoryViewTraffic getViewTraffic() throws IOException{ + return root.retrieve().to(getApiTailUrl("/traffic/views"), GHRepositoryViewTraffic.class); } /** * https://developer.github.com/v3/repos/traffic/#clones */ - public GHRepositoryClones getClones() throws IOException{ - return root.retrieve().to(getApiTailUrl("/traffic/clones"), GHRepositoryClones.class); + public GHRepositoryCloneTraffic getCloneTraffic() throws IOException{ + return root.retrieve().to(getApiTailUrl("/traffic/clones"), GHRepositoryCloneTraffic.class); } @Override diff --git a/src/main/java/org/kohsuke/github/GHRepositoryCloneTraffic.java b/src/main/java/org/kohsuke/github/GHRepositoryCloneTraffic.java new file mode 100644 index 0000000000..497392deb2 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHRepositoryCloneTraffic.java @@ -0,0 +1,42 @@ +package org.kohsuke.github; + +import java.util.Date; +import java.util.List; + +/** + * Repository clone statistics. + * + * @see GHRepository#getCloneTraffic() + */ +public class GHRepositoryCloneTraffic extends GHRepositoryTrafficInfo { + private List clones; + + /*package*/ GHRepositoryCloneTraffic() { + } + + /*package*/ GHRepositoryCloneTraffic(Integer count, Integer uniques, List clones) { + super(count, uniques); + this.clones = clones; + } + + public List getClones() { + return clones; + } + + public List getDailyInfo() { + return getClones(); + } + + public static class DayInfo extends GHRepositoryTrafficInfo.DayInfo { + /*package*/ DayInfo() { + } + + /*package*/ DayInfo(String timestamp, int count, int uniques) { + super(timestamp, count, uniques); + } + + /*package*/ DayInfo(Date timestamp, int count, int uniques) { + super(timestamp, count, uniques); + } + } +} diff --git a/src/main/java/org/kohsuke/github/GHRepositoryClones.java b/src/main/java/org/kohsuke/github/GHRepositoryClones.java deleted file mode 100644 index 1bd126038a..0000000000 --- a/src/main/java/org/kohsuke/github/GHRepositoryClones.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.kohsuke.github; - -import java.util.Date; -import java.util.List; - -/** - * Repository clone statistics. - * - * @see GHRepository#getClones() - */ -public class GHRepositoryClones extends GHRepositoryTrafficInfo { - private List clones; - - /*package*/ GHRepositoryClones() { - } - - /*package*/ GHRepositoryClones(Integer count, Integer uniques, List clones) { - super(count, uniques); - this.clones = clones; - } - - public List getClones() { - return clones; - } - - public List getDailyInfo() { - return getClones(); - } - - public static class DayClones extends GHRepositoryTrafficInfo.DayInfo { - /*package*/ DayClones() { - } - - /*package*/ DayClones(String timestamp, int count, int uniques) { - super(timestamp, count, uniques); - } - - /*package*/ DayClones(Date timestamp, int count, int uniques) { - super(timestamp, count, uniques); - } - } -} diff --git a/src/main/java/org/kohsuke/github/GHRepositoryViewTraffic.java b/src/main/java/org/kohsuke/github/GHRepositoryViewTraffic.java new file mode 100644 index 0000000000..42c716cc6e --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHRepositoryViewTraffic.java @@ -0,0 +1,42 @@ +package org.kohsuke.github; + +import java.util.Date; +import java.util.List; + +/** + * Repository view statistics. + * + * @see GHRepository#getViewTraffic() + */ +public class GHRepositoryViewTraffic extends GHRepositoryTrafficInfo { + private List views; + + /*package*/ GHRepositoryViewTraffic() { + } + + /*package*/ GHRepositoryViewTraffic(int count, int uniques, List views) { + super(count, uniques); + this.views = views; + } + + public List getViews() { + return views; + } + + public List getDailyInfo() { + return getViews(); + } + + public static class Daily extends GHRepositoryTrafficInfo.DayInfo { + /*package*/ Daily() { + } + + /*package*/ Daily(String timestamp, int count, int uniques) { + super(timestamp, count, uniques); + } + + /*package*/ Daily(Date timestamp, int count, int uniques) { + super(timestamp, count, uniques); + } + } +} diff --git a/src/main/java/org/kohsuke/github/GHRepositoryViews.java b/src/main/java/org/kohsuke/github/GHRepositoryViews.java deleted file mode 100644 index 2f7ea80f78..0000000000 --- a/src/main/java/org/kohsuke/github/GHRepositoryViews.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.kohsuke.github; - -import java.util.Date; -import java.util.List; - -/** - * Repository view statistics. - * - * @see GHRepository#getViews() - */ -public class GHRepositoryViews extends GHRepositoryTrafficInfo { - private List views; - - /*package*/ GHRepositoryViews() { - } - - /*package*/ GHRepositoryViews(int count, int uniques, List views) { - super(count, uniques); - this.views = views; - } - - public List getViews() { - return views; - } - - public List getDailyInfo() { - return getViews(); - } - - public static class DayViews extends GHRepositoryTrafficInfo.DayInfo { - /*package*/ DayViews() { - } - - /*package*/ DayViews(String timestamp, int count, int uniques) { - super(timestamp, count, uniques); - } - - /*package*/ DayViews(Date timestamp, int count, int uniques) { - super(timestamp, count, uniques); - } - } -} diff --git a/src/test/java/org/kohsuke/github/RepositoryTrafficTest.java b/src/test/java/org/kohsuke/github/RepositoryTrafficTest.java index 66cccd7ed3..64864acfa2 100644 --- a/src/test/java/org/kohsuke/github/RepositoryTrafficTest.java +++ b/src/test/java/org/kohsuke/github/RepositoryTrafficTest.java @@ -4,7 +4,8 @@ import org.apache.commons.io.IOUtils; import org.junit.Assert; import org.junit.Test; -import org.kohsuke.github.GHRepositoryTrafficInfo.DayInfo; +import org.kohsuke.github.GHRepositoryCloneTraffic.DayInfo; +import org.kohsuke.github.GHRepositoryViewTraffic.Daily; import org.mockito.Mockito; import java.io.IOException; @@ -25,18 +26,18 @@ private void checkResponse(T expected, T act Assert.assertEquals(expected.getCount(), actual.getCount()); Assert.assertEquals(expected.getUniques(), actual.getUniques()); - List expectedList = expected.getDailyInfo(); - List actualList = actual.getDailyInfo(); - Iterator expectedIt; - Iterator actualIt; + List expectedList = expected.getDailyInfo(); + List actualList = actual.getDailyInfo(); + Iterator expectedIt; + Iterator actualIt; Assert.assertEquals(expectedList.size(), actualList.size()); expectedIt = expectedList.iterator(); actualIt = actualList.iterator(); while(expectedIt.hasNext() && actualIt.hasNext()) { - DayInfo expectedDayInfo = expectedIt.next(); - DayInfo actualDayInfo = actualIt.next(); + GHRepositoryTrafficInfo.DayInfo expectedDayInfo = expectedIt.next(); + GHRepositoryTrafficInfo.DayInfo actualDayInfo = actualIt.next(); Assert.assertEquals(expectedDayInfo.getCount(), actualDayInfo.getCount()); Assert.assertEquals(expectedDayInfo.getUniques(), actualDayInfo.getUniques()); Assert.assertEquals(expectedDayInfo.getTimestamp(), actualDayInfo.getTimestamp()); @@ -73,7 +74,7 @@ private void testTraffic(T expectedResult) t // this covers calls on "uc" in Requester.setupConnection and Requester.buildRequest URL trafficURL = new URL( "https://api.github.com/repos/"+login+"/"+repositoryName+"/traffic/" + - ((expectedResult instanceof GHRepositoryViews) ? "views" : "clones") + ((expectedResult instanceof GHRepositoryViewTraffic) ? "views" : "clones") ); Mockito.doReturn(mockHttpURLConnection).when(connectorSpy).connect(Mockito.eq(trafficURL)); @@ -84,37 +85,37 @@ private void testTraffic(T expectedResult) t InputStream stubInputStream = IOUtils.toInputStream(mockedResponse, "UTF-8"); Mockito.doReturn(stubInputStream).when(mockHttpURLConnection).getInputStream(); - if(expectedResult instanceof GHRepositoryViews){ - GHRepositoryViews views = repo.getViews(); + if(expectedResult instanceof GHRepositoryViewTraffic){ + GHRepositoryViewTraffic views = repo.getViewTraffic(); checkResponse(expectedResult, views); } - else if(expectedResult instanceof GHRepositoryClones) { - GHRepositoryClones clones = repo.getClones(); + else if(expectedResult instanceof GHRepositoryCloneTraffic) { + GHRepositoryCloneTraffic clones = repo.getCloneTraffic(); checkResponse(expectedResult, clones); } } @Test public void testGetViews() throws IOException{ - GHRepositoryViews expectedResult = new GHRepositoryViews( + GHRepositoryViewTraffic expectedResult = new GHRepositoryViewTraffic( 21523359, 65534, Arrays.asList( - new GHRepositoryViews.DayViews("2016-10-10T00:00:00Z", 3, 2), - new GHRepositoryViews.DayViews("2016-10-11T00:00:00Z", 9, 4), - new GHRepositoryViews.DayViews("2016-10-12T00:00:00Z", 27, 8), - new GHRepositoryViews.DayViews("2016-10-13T00:00:00Z", 81, 16), - new GHRepositoryViews.DayViews("2016-10-14T00:00:00Z", 243, 32), - new GHRepositoryViews.DayViews("2016-10-15T00:00:00Z", 729, 64), - new GHRepositoryViews.DayViews("2016-10-16T00:00:00Z", 2187, 128), - new GHRepositoryViews.DayViews("2016-10-17T00:00:00Z", 6561, 256), - new GHRepositoryViews.DayViews("2016-10-18T00:00:00Z", 19683, 512), - new GHRepositoryViews.DayViews("2016-10-19T00:00:00Z", 59049, 1024), - new GHRepositoryViews.DayViews("2016-10-20T00:00:00Z", 177147, 2048), - new GHRepositoryViews.DayViews("2016-10-21T00:00:00Z", 531441, 4096), - new GHRepositoryViews.DayViews("2016-10-22T00:00:00Z", 1594323, 8192), - new GHRepositoryViews.DayViews("2016-10-23T00:00:00Z", 4782969, 16384), - new GHRepositoryViews.DayViews("2016-10-24T00:00:00Z", 14348907, 32768) + new Daily("2016-10-10T00:00:00Z", 3, 2), + new Daily("2016-10-11T00:00:00Z", 9, 4), + new Daily("2016-10-12T00:00:00Z", 27, 8), + new Daily("2016-10-13T00:00:00Z", 81, 16), + new Daily("2016-10-14T00:00:00Z", 243, 32), + new Daily("2016-10-15T00:00:00Z", 729, 64), + new Daily("2016-10-16T00:00:00Z", 2187, 128), + new Daily("2016-10-17T00:00:00Z", 6561, 256), + new Daily("2016-10-18T00:00:00Z", 19683, 512), + new Daily("2016-10-19T00:00:00Z", 59049, 1024), + new Daily("2016-10-20T00:00:00Z", 177147, 2048), + new Daily("2016-10-21T00:00:00Z", 531441, 4096), + new Daily("2016-10-22T00:00:00Z", 1594323, 8192), + new Daily("2016-10-23T00:00:00Z", 4782969, 16384), + new Daily("2016-10-24T00:00:00Z", 14348907, 32768) ) ); testTraffic(expectedResult); @@ -122,25 +123,25 @@ public void testGetViews() throws IOException{ @Test public void testGetClones() throws IOException{ - GHRepositoryClones expectedResult = new GHRepositoryClones( + GHRepositoryCloneTraffic expectedResult = new GHRepositoryCloneTraffic( 1500, 455, Arrays.asList( - new GHRepositoryClones.DayClones("2016-10-10T00:00:00Z", 10,3), - new GHRepositoryClones.DayClones("2016-10-11T00:00:00Z", 20,6), - new GHRepositoryClones.DayClones("2016-10-12T00:00:00Z", 30,5), - new GHRepositoryClones.DayClones("2016-10-13T00:00:00Z", 40,7), - new GHRepositoryClones.DayClones("2016-10-14T00:00:00Z", 50,11), - new GHRepositoryClones.DayClones("2016-10-15T00:00:00Z", 60,12), - new GHRepositoryClones.DayClones("2016-10-16T00:00:00Z", 70,19), - new GHRepositoryClones.DayClones("2016-10-17T00:00:00Z", 170,111), - new GHRepositoryClones.DayClones("2016-10-18T00:00:00Z", 180,70), - new GHRepositoryClones.DayClones("2016-10-19T00:00:00Z", 190,10), - new GHRepositoryClones.DayClones("2016-10-20T00:00:00Z", 200,18), - new GHRepositoryClones.DayClones("2016-10-21T00:00:00Z", 210,8), - new GHRepositoryClones.DayClones("2016-10-22T00:00:00Z", 220,168), - new GHRepositoryClones.DayClones("2016-10-23T00:00:00Z", 5,2), - new GHRepositoryClones.DayClones("2016-10-24T00:00:00Z", 45,5) + new DayInfo("2016-10-10T00:00:00Z", 10,3), + new DayInfo("2016-10-11T00:00:00Z", 20,6), + new DayInfo("2016-10-12T00:00:00Z", 30,5), + new DayInfo("2016-10-13T00:00:00Z", 40,7), + new DayInfo("2016-10-14T00:00:00Z", 50,11), + new DayInfo("2016-10-15T00:00:00Z", 60,12), + new DayInfo("2016-10-16T00:00:00Z", 70,19), + new DayInfo("2016-10-17T00:00:00Z", 170,111), + new DayInfo("2016-10-18T00:00:00Z", 180,70), + new DayInfo("2016-10-19T00:00:00Z", 190,10), + new DayInfo("2016-10-20T00:00:00Z", 200,18), + new DayInfo("2016-10-21T00:00:00Z", 210,8), + new DayInfo("2016-10-22T00:00:00Z", 220,168), + new DayInfo("2016-10-23T00:00:00Z", 5,2), + new DayInfo("2016-10-24T00:00:00Z", 45,5) ) ); testTraffic(expectedResult); @@ -152,13 +153,13 @@ public void testGetTrafficStatsAccessFailureDueToInsufficientPermissions() throw GitHub gitHub = GitHub.connect(login, null); GHRepository repo = gitHub.getUser(login).getRepository(repositoryName); try { - repo.getViews(); + repo.getViewTraffic(); Assert.fail(errorMsg); } catch (HttpException ex){ } try { - repo.getClones(); + repo.getCloneTraffic(); Assert.fail(errorMsg); } catch (HttpException ex){ From bbc2f3962f55de88413e88243d11a49c816a09b7 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 11:44:02 -0700 Subject: [PATCH 277/390] Proper access control modifier --- src/main/java/org/kohsuke/github/GHBlobBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHBlobBuilder.java b/src/main/java/org/kohsuke/github/GHBlobBuilder.java index 321e88191d..0ab62aeafb 100644 --- a/src/main/java/org/kohsuke/github/GHBlobBuilder.java +++ b/src/main/java/org/kohsuke/github/GHBlobBuilder.java @@ -12,7 +12,7 @@ public class GHBlobBuilder { private final GHRepository repo; private final Requester req; - public GHBlobBuilder(GHRepository repo) { + GHBlobBuilder(GHRepository repo) { this.repo = repo; req = new Requester(repo.root); } From 9cf6ee78d4a0fe03676f608ce5bb449f9df3f663 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 11:44:09 -0700 Subject: [PATCH 278/390] Pointless string conversion --- src/main/java/org/kohsuke/github/GHBlobBuilder.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHBlobBuilder.java b/src/main/java/org/kohsuke/github/GHBlobBuilder.java index 0ab62aeafb..a6259e5b6d 100644 --- a/src/main/java/org/kohsuke/github/GHBlobBuilder.java +++ b/src/main/java/org/kohsuke/github/GHBlobBuilder.java @@ -30,7 +30,6 @@ public GHBlobBuilder textContent(String content) { * Configures a blob with the specified binary {@code content}. */ public GHBlobBuilder binaryContent(byte[] content) { - new String(content); String base64Content = Base64.encodeBase64String(content); req.with("content", base64Content); req.with("encoding", "base64"); From f3a3b8786122d3f78df61a64db36a0d2288817df Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 11:48:25 -0700 Subject: [PATCH 279/390] Defined entry points --- .../java/org/kohsuke/github/GHCommitBuilder.java | 2 +- src/main/java/org/kohsuke/github/GHRepository.java | 12 ++++++++++++ src/main/java/org/kohsuke/github/GHTreeBuilder.java | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHCommitBuilder.java b/src/main/java/org/kohsuke/github/GHCommitBuilder.java index 5f5b268a63..76e846a7d7 100644 --- a/src/main/java/org/kohsuke/github/GHCommitBuilder.java +++ b/src/main/java/org/kohsuke/github/GHCommitBuilder.java @@ -33,7 +33,7 @@ private UserInfo(String name, String email, Date date) { } } - public GHCommitBuilder(GHRepository repo) { + GHCommitBuilder(GHRepository repo) { this.repo = repo; req = new Requester(repo.root); } diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 74fbb4d665..2e15f089f7 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -824,6 +824,10 @@ public GHTree getTree(String sha) throws IOException { return root.retrieve().to(url, GHTree.class).wrap(this); } + public GHTreeBuilder createTree() { + return new GHTreeBuilder(this); + } + /** * Retrieves the tree for the current GitHub repository, recursively as described in here: * https://developer.github.com/v3/git/trees/#get-a-tree-recursively @@ -853,6 +857,10 @@ public GHBlob getBlob(String blobSha) throws IOException { return root.retrieve().to(target, GHBlob.class); } + public GHBlobBuilder createBlob() { + return new GHBlobBuilder(this); + } + /** * Reads the content of a blob as a stream for better efficiency. * @@ -876,6 +884,10 @@ public GHCommit getCommit(String sha1) throws IOException { return c; } + public GHCommitBuilder createCommit() { + return new GHCommitBuilder(this); + } + /** * Lists all the commits. */ diff --git a/src/main/java/org/kohsuke/github/GHTreeBuilder.java b/src/main/java/org/kohsuke/github/GHTreeBuilder.java index 05c04ef9c1..46fe43b4ad 100644 --- a/src/main/java/org/kohsuke/github/GHTreeBuilder.java +++ b/src/main/java/org/kohsuke/github/GHTreeBuilder.java @@ -27,7 +27,7 @@ private TreeEntry(String path, String mode, String type) { } } - public GHTreeBuilder(GHRepository repo) { + GHTreeBuilder(GHRepository repo) { this.repo = repo; req = new Requester(repo.root); } From 8928a8a1dcedd33ef5cec103ca8c4ab5cb6074a7 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 11:51:55 -0700 Subject: [PATCH 280/390] Content type should be JSON by default when sending JSON. This solves #350 a little differently. --- src/main/java/org/kohsuke/github/Requester.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index 576d313f5d..beeef0d2e2 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -60,6 +60,7 @@ import static java.util.Arrays.asList; import java.util.logging.Level; import static java.util.logging.Level.*; +import static org.apache.commons.lang.StringUtils.defaultString; import static org.kohsuke.github.GitHub.MAPPER; /** @@ -76,7 +77,7 @@ class Requester { * Request method. */ private String method = "POST"; - private String contentType = "application/x-www-form-urlencoded"; + private String contentType = null; private InputStream body; /** @@ -392,18 +393,19 @@ public String getResponseHeader(String header) { private void buildRequest() throws IOException { if (isMethodWithBody()) { uc.setDoOutput(true); - uc.setRequestProperty("Content-type", contentType); if (body == null) { + uc.setRequestProperty("Content-type", defaultString(contentType,"application/json")); Map json = new HashMap(); for (Entry e : args) { json.put(e.key, e.value); } MAPPER.writeValue(uc.getOutputStream(), json); } else { + uc.setRequestProperty("Content-type", defaultString(contentType,"application/x-www-form-urlencoded")); try { byte[] bytes = new byte[32768]; - int read = 0; + int read; while ((read = body.read(bytes)) != -1) { uc.getOutputStream().write(bytes, 0, read); } From 17edd33703a323ebec53dfc912eb3028826105c7 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 12:00:23 -0700 Subject: [PATCH 281/390] Reorganized imports following #337 --- .../org/kohsuke/github/GHAuthorization.java | 1 + .../java/org/kohsuke/github/GHBranch.java | 7 +++---- .../kohsuke/github/GHBranchProtection.java | 5 ++--- .../github/GHBranchProtectionBuilder.java | 4 ++-- .../java/org/kohsuke/github/GHCommit.java | 1 + .../org/kohsuke/github/GHCommitComment.java | 4 +++- .../kohsuke/github/GHCommitSearchBuilder.java | 4 ++-- .../java/org/kohsuke/github/GHDeployKey.java | 4 ++-- .../java/org/kohsuke/github/GHEventInfo.java | 6 +++--- .../org/kohsuke/github/GHEventPayload.java | 1 + src/main/java/org/kohsuke/github/GHHook.java | 1 + .../org/kohsuke/github/GHIssueComment.java | 2 +- .../java/org/kohsuke/github/GHLicense.java | 2 +- .../java/org/kohsuke/github/GHObject.java | 1 + .../org/kohsuke/github/GHPullRequest.java | 4 ++-- .../kohsuke/github/GHPullRequestReview.java | 2 +- .../java/org/kohsuke/github/GHRateLimit.java | 1 + .../java/org/kohsuke/github/GHReaction.java | 2 +- src/main/java/org/kohsuke/github/GHRef.java | 1 + .../java/org/kohsuke/github/GHRelease.java | 2 +- .../java/org/kohsuke/github/GHThread.java | 1 + .../org/kohsuke/github/GHTreeBuilder.java | 3 ++- src/main/java/org/kohsuke/github/GitHub.java | 20 +++++++++---------- src/main/java/org/kohsuke/github/GitUser.java | 1 + .../org/kohsuke/github/HttpException.java | 3 +-- .../java/org/kohsuke/github/Requester.java | 15 +++++++------- 26 files changed, 54 insertions(+), 44 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHAuthorization.java b/src/main/java/org/kohsuke/github/GHAuthorization.java index e196047776..bf7e24c7f2 100644 --- a/src/main/java/org/kohsuke/github/GHAuthorization.java +++ b/src/main/java/org/kohsuke/github/GHAuthorization.java @@ -1,6 +1,7 @@ package org.kohsuke.github; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + import java.net.URL; import java.util.Collection; import java.util.List; diff --git a/src/main/java/org/kohsuke/github/GHBranch.java b/src/main/java/org/kohsuke/github/GHBranch.java index c2e5b29441..1ce9c29ac4 100644 --- a/src/main/java/org/kohsuke/github/GHBranch.java +++ b/src/main/java/org/kohsuke/github/GHBranch.java @@ -1,14 +1,13 @@ package org.kohsuke.github; -import static org.kohsuke.github.Previews.LOKI; +import com.fasterxml.jackson.annotation.JsonProperty; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.io.IOException; import java.net.URL; import java.util.Collection; -import com.fasterxml.jackson.annotation.JsonProperty; - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import static org.kohsuke.github.Previews.*; /** * A branch in a repository. diff --git a/src/main/java/org/kohsuke/github/GHBranchProtection.java b/src/main/java/org/kohsuke/github/GHBranchProtection.java index 3216366115..7e43bd69cb 100644 --- a/src/main/java/org/kohsuke/github/GHBranchProtection.java +++ b/src/main/java/org/kohsuke/github/GHBranchProtection.java @@ -1,11 +1,10 @@ package org.kohsuke.github; -import java.util.Collection; - import com.fasterxml.jackson.annotation.JsonProperty; - import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import java.util.Collection; + @SuppressFBWarnings(value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD", "URF_UNREAD_FIELD" }, justification = "JSON API") public class GHBranchProtection { diff --git a/src/main/java/org/kohsuke/github/GHBranchProtectionBuilder.java b/src/main/java/org/kohsuke/github/GHBranchProtectionBuilder.java index 5fccf7eb8c..dc7dbd8845 100644 --- a/src/main/java/org/kohsuke/github/GHBranchProtectionBuilder.java +++ b/src/main/java/org/kohsuke/github/GHBranchProtectionBuilder.java @@ -1,6 +1,6 @@ package org.kohsuke.github; -import static org.kohsuke.github.Previews.LOKI; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.io.IOException; import java.util.ArrayList; @@ -12,7 +12,7 @@ import java.util.Map; import java.util.Set; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import static org.kohsuke.github.Previews.*; /** * Builder to configure the branch protection settings. diff --git a/src/main/java/org/kohsuke/github/GHCommit.java b/src/main/java/org/kohsuke/github/GHCommit.java index ec5dfbffc1..a817da2fd6 100644 --- a/src/main/java/org/kohsuke/github/GHCommit.java +++ b/src/main/java/org/kohsuke/github/GHCommit.java @@ -2,6 +2,7 @@ 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.AbstractList; diff --git a/src/main/java/org/kohsuke/github/GHCommitComment.java b/src/main/java/org/kohsuke/github/GHCommitComment.java index 646badf5c3..f5ee76e478 100644 --- a/src/main/java/org/kohsuke/github/GHCommitComment.java +++ b/src/main/java/org/kohsuke/github/GHCommitComment.java @@ -1,9 +1,11 @@ package org.kohsuke.github; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + import java.io.IOException; import java.net.URL; -import static org.kohsuke.github.Previews.SQUIRREL_GIRL; + +import static org.kohsuke.github.Previews.*; /** * A comment attached to a commit (or a specific line in a specific file of a commit.) diff --git a/src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java b/src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java index 65136dc0a4..23960528f2 100644 --- a/src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java +++ b/src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java @@ -1,9 +1,9 @@ package org.kohsuke.github; -import java.io.IOException; - import org.apache.commons.lang.StringUtils; +import java.io.IOException; + /** * Search commits. * diff --git a/src/main/java/org/kohsuke/github/GHDeployKey.java b/src/main/java/org/kohsuke/github/GHDeployKey.java index eb2c2c00fb..bfa03b2508 100644 --- a/src/main/java/org/kohsuke/github/GHDeployKey.java +++ b/src/main/java/org/kohsuke/github/GHDeployKey.java @@ -1,9 +1,9 @@ package org.kohsuke.github; -import java.io.IOException; - import org.apache.commons.lang.builder.ToStringBuilder; +import java.io.IOException; + public class GHDeployKey { protected String url, key, title; diff --git a/src/main/java/org/kohsuke/github/GHEventInfo.java b/src/main/java/org/kohsuke/github/GHEventInfo.java index 0268924ea2..e875f2df59 100644 --- a/src/main/java/org/kohsuke/github/GHEventInfo.java +++ b/src/main/java/org/kohsuke/github/GHEventInfo.java @@ -1,11 +1,11 @@ package org.kohsuke.github; -import java.io.IOException; -import java.util.Date; - import com.fasterxml.jackson.databind.node.ObjectNode; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import java.io.IOException; +import java.util.Date; + /** * Represents an event. * diff --git a/src/main/java/org/kohsuke/github/GHEventPayload.java b/src/main/java/org/kohsuke/github/GHEventPayload.java index 29f69bb3eb..8f5799430f 100644 --- a/src/main/java/org/kohsuke/github/GHEventPayload.java +++ b/src/main/java/org/kohsuke/github/GHEventPayload.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonSetter; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + import java.io.Reader; import java.util.List; diff --git a/src/main/java/org/kohsuke/github/GHHook.java b/src/main/java/org/kohsuke/github/GHHook.java index 4aa32e1946..b7f450307a 100644 --- a/src/main/java/org/kohsuke/github/GHHook.java +++ b/src/main/java/org/kohsuke/github/GHHook.java @@ -1,6 +1,7 @@ package org.kohsuke.github; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + import java.io.IOException; import java.net.URL; import java.util.Collections; diff --git a/src/main/java/org/kohsuke/github/GHIssueComment.java b/src/main/java/org/kohsuke/github/GHIssueComment.java index a98f6f6398..3f4d70643d 100644 --- a/src/main/java/org/kohsuke/github/GHIssueComment.java +++ b/src/main/java/org/kohsuke/github/GHIssueComment.java @@ -26,7 +26,7 @@ import java.io.IOException; import java.net.URL; -import static org.kohsuke.github.Previews.SQUIRREL_GIRL; +import static org.kohsuke.github.Previews.*; /** * Comment to the issue diff --git a/src/main/java/org/kohsuke/github/GHLicense.java b/src/main/java/org/kohsuke/github/GHLicense.java index 2c5c4299c1..a7dad4b5ca 100644 --- a/src/main/java/org/kohsuke/github/GHLicense.java +++ b/src/main/java/org/kohsuke/github/GHLicense.java @@ -32,7 +32,7 @@ import java.util.ArrayList; import java.util.List; -import static org.kohsuke.github.Previews.DRAX; +import static org.kohsuke.github.Previews.*; /** * The GitHub Preview API's license information diff --git a/src/main/java/org/kohsuke/github/GHObject.java b/src/main/java/org/kohsuke/github/GHObject.java index d368af0aec..e091981909 100644 --- a/src/main/java/org/kohsuke/github/GHObject.java +++ b/src/main/java/org/kohsuke/github/GHObject.java @@ -4,6 +4,7 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.apache.commons.lang.builder.ReflectionToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; + import java.io.IOException; import java.lang.reflect.Field; import java.net.URL; diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index 078603d6fa..677d6bede6 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -23,6 +23,7 @@ */ package org.kohsuke.github; +import javax.annotation.CheckForNull; import java.io.IOException; import java.net.URL; import java.util.ArrayList; @@ -30,9 +31,8 @@ import java.util.Collection; import java.util.Date; import java.util.List; -import javax.annotation.CheckForNull; -import static org.kohsuke.github.Previews.BLACK_CAT; +import static org.kohsuke.github.Previews.*; /** * A pull request. diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReview.java b/src/main/java/org/kohsuke/github/GHPullRequestReview.java index b25f28b59a..d7afe59aad 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestReview.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestReview.java @@ -26,7 +26,7 @@ import java.io.IOException; import java.net.URL; -import static org.kohsuke.github.Previews.BLACK_CAT; +import static org.kohsuke.github.Previews.*; /** * Review to the pull request diff --git a/src/main/java/org/kohsuke/github/GHRateLimit.java b/src/main/java/org/kohsuke/github/GHRateLimit.java index b9b900d785..9500b0a736 100644 --- a/src/main/java/org/kohsuke/github/GHRateLimit.java +++ b/src/main/java/org/kohsuke/github/GHRateLimit.java @@ -1,6 +1,7 @@ package org.kohsuke.github; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + import java.util.Date; /** diff --git a/src/main/java/org/kohsuke/github/GHReaction.java b/src/main/java/org/kohsuke/github/GHReaction.java index 55b26365e0..6a00eb305c 100644 --- a/src/main/java/org/kohsuke/github/GHReaction.java +++ b/src/main/java/org/kohsuke/github/GHReaction.java @@ -3,7 +3,7 @@ import java.io.IOException; import java.net.URL; -import static org.kohsuke.github.Previews.SQUIRREL_GIRL; +import static org.kohsuke.github.Previews.*; /** * Reaction to issue, comment, PR, and so on. diff --git a/src/main/java/org/kohsuke/github/GHRef.java b/src/main/java/org/kohsuke/github/GHRef.java index 8212dc2c3b..c8462d3fe6 100644 --- a/src/main/java/org/kohsuke/github/GHRef.java +++ b/src/main/java/org/kohsuke/github/GHRef.java @@ -1,6 +1,7 @@ package org.kohsuke.github; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + import java.io.IOException; import java.net.URL; diff --git a/src/main/java/org/kohsuke/github/GHRelease.java b/src/main/java/org/kohsuke/github/GHRelease.java index 96421da415..524bce70b4 100644 --- a/src/main/java/org/kohsuke/github/GHRelease.java +++ b/src/main/java/org/kohsuke/github/GHRelease.java @@ -8,7 +8,7 @@ import java.util.Date; import java.util.List; -import static java.lang.String.format; +import static java.lang.String.*; /** * Release in a github repository. diff --git a/src/main/java/org/kohsuke/github/GHThread.java b/src/main/java/org/kohsuke/github/GHThread.java index a1964b10de..faf4c87b7b 100644 --- a/src/main/java/org/kohsuke/github/GHThread.java +++ b/src/main/java/org/kohsuke/github/GHThread.java @@ -1,6 +1,7 @@ package org.kohsuke.github; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + import java.io.FileNotFoundException; import java.io.IOException; import java.net.URL; diff --git a/src/main/java/org/kohsuke/github/GHTreeBuilder.java b/src/main/java/org/kohsuke/github/GHTreeBuilder.java index 46fe43b4ad..cffbc8eafd 100644 --- a/src/main/java/org/kohsuke/github/GHTreeBuilder.java +++ b/src/main/java/org/kohsuke/github/GHTreeBuilder.java @@ -1,7 +1,8 @@ package org.kohsuke.github; import java.io.IOException; -import java.util.*; +import java.util.ArrayList; +import java.util.List; /** * Builder pattern for creating a new tree. diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 49c860e4dc..f9f9f6decf 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -27,6 +27,12 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.introspect.VisibilityChecker.Std; import com.infradna.tool.bridge_method_injector.WithBridgeMethods; +import org.apache.commons.codec.Charsets; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.io.IOUtils; + +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; import java.io.ByteArrayInputStream; import java.io.FileNotFoundException; import java.io.IOException; @@ -48,17 +54,11 @@ import java.util.Set; import java.util.TimeZone; import java.util.logging.Logger; -import javax.annotation.CheckForNull; -import javax.annotation.Nonnull; -import org.apache.commons.codec.Charsets; -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.io.IOUtils; -import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.ANY; -import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE; -import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; -import static java.util.logging.Level.FINE; -import static org.kohsuke.github.Previews.DRAX; +import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.*; +import static java.net.HttpURLConnection.*; +import static java.util.logging.Level.*; +import static org.kohsuke.github.Previews.*; /** * Root of the GitHub API. diff --git a/src/main/java/org/kohsuke/github/GitUser.java b/src/main/java/org/kohsuke/github/GitUser.java index 751aabd378..9cd50bb22a 100644 --- a/src/main/java/org/kohsuke/github/GitUser.java +++ b/src/main/java/org/kohsuke/github/GitUser.java @@ -1,6 +1,7 @@ package org.kohsuke.github; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + import java.util.Date; /** diff --git a/src/main/java/org/kohsuke/github/HttpException.java b/src/main/java/org/kohsuke/github/HttpException.java index 16c8e68be2..79def83c2a 100644 --- a/src/main/java/org/kohsuke/github/HttpException.java +++ b/src/main/java/org/kohsuke/github/HttpException.java @@ -1,11 +1,10 @@ package org.kohsuke.github; +import javax.annotation.CheckForNull; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; -import javax.annotation.CheckForNull; - /** * {@link IOException} for http exceptions because {@link HttpURLConnection} throws un-discerned * {@link IOException} and it can help to know the http response code to decide how to handle an diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index beeef0d2e2..3e28c342f7 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -25,6 +25,10 @@ import com.fasterxml.jackson.databind.JsonMappingException; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringUtils; + +import javax.annotation.WillClose; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; @@ -49,19 +53,16 @@ import java.util.Locale; import java.util.Map; import java.util.NoSuchElementException; +import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.GZIPInputStream; -import javax.annotation.WillClose; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; -import static java.util.Arrays.asList; -import java.util.logging.Level; +import static java.util.Arrays.*; import static java.util.logging.Level.*; -import static org.apache.commons.lang.StringUtils.defaultString; -import static org.kohsuke.github.GitHub.MAPPER; +import static org.apache.commons.lang.StringUtils.*; +import static org.kohsuke.github.GitHub.*; /** * A builder pattern for making HTTP call and parsing its output. From 635350c40e346611506839bb4007be15e3ceeda8 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 12:02:44 -0700 Subject: [PATCH 282/390] Additional naming consistency change --- .../github/GHRepositoryCloneTraffic.java | 21 ++--- ...fficInfo.java => GHRepositoryTraffic.java} | 24 ++---- .../github/GHRepositoryViewTraffic.java | 21 ++--- .../kohsuke/github/RepositoryTrafficTest.java | 84 +++++++++---------- 4 files changed, 66 insertions(+), 84 deletions(-) rename src/main/java/org/kohsuke/github/{GHRepositoryTrafficInfo.java => GHRepositoryTraffic.java} (50%) diff --git a/src/main/java/org/kohsuke/github/GHRepositoryCloneTraffic.java b/src/main/java/org/kohsuke/github/GHRepositoryCloneTraffic.java index 497392deb2..c75198e4a8 100644 --- a/src/main/java/org/kohsuke/github/GHRepositoryCloneTraffic.java +++ b/src/main/java/org/kohsuke/github/GHRepositoryCloneTraffic.java @@ -1,6 +1,5 @@ package org.kohsuke.github; -import java.util.Date; import java.util.List; /** @@ -8,34 +7,30 @@ * * @see GHRepository#getCloneTraffic() */ -public class GHRepositoryCloneTraffic extends GHRepositoryTrafficInfo { - private List clones; +public class GHRepositoryCloneTraffic extends GHRepositoryTraffic { + private List clones; /*package*/ GHRepositoryCloneTraffic() { } - /*package*/ GHRepositoryCloneTraffic(Integer count, Integer uniques, List clones) { + /*package*/ GHRepositoryCloneTraffic(Integer count, Integer uniques, List clones) { super(count, uniques); this.clones = clones; } - public List getClones() { + public List getClones() { return clones; } - public List getDailyInfo() { + public List getDailyInfo() { return getClones(); } - public static class DayInfo extends GHRepositoryTrafficInfo.DayInfo { - /*package*/ DayInfo() { + public static class DailyInfo extends GHRepositoryTraffic.DailyInfo { + /*package*/ DailyInfo() { } - /*package*/ DayInfo(String timestamp, int count, int uniques) { - super(timestamp, count, uniques); - } - - /*package*/ DayInfo(Date timestamp, int count, int uniques) { + /*package*/ DailyInfo(String timestamp, int count, int uniques) { super(timestamp, count, uniques); } } diff --git a/src/main/java/org/kohsuke/github/GHRepositoryTrafficInfo.java b/src/main/java/org/kohsuke/github/GHRepositoryTraffic.java similarity index 50% rename from src/main/java/org/kohsuke/github/GHRepositoryTrafficInfo.java rename to src/main/java/org/kohsuke/github/GHRepositoryTraffic.java index 7336c93285..42d07e848d 100644 --- a/src/main/java/org/kohsuke/github/GHRepositoryTrafficInfo.java +++ b/src/main/java/org/kohsuke/github/GHRepositoryTraffic.java @@ -3,14 +3,14 @@ import java.util.Date; import java.util.List; -public abstract class GHRepositoryTrafficInfo implements TrafficInfo { +public abstract class GHRepositoryTraffic implements TrafficInfo { private int count; private int uniques; - /*package*/ GHRepositoryTrafficInfo() { + /*package*/ GHRepositoryTraffic() { } - /*package*/ GHRepositoryTrafficInfo(int count, int uniques) { + /*package*/ GHRepositoryTraffic(int count, int uniques) { this.count = count; this.uniques = uniques; } @@ -23,15 +23,15 @@ public int getUniques() { return uniques; } - public abstract List getDailyInfo(); + public abstract List getDailyInfo(); - public static abstract class DayInfo implements TrafficInfo { - private Date timestamp; + public static abstract class DailyInfo implements TrafficInfo { + private String timestamp; private int count; private int uniques; public Date getTimestamp() { - return timestamp; + return GitHub.parseDate(timestamp); } public int getCount() { @@ -42,16 +42,10 @@ public int getUniques() { return uniques; } - /*package*/ DayInfo() { + /*package*/ DailyInfo() { } - /*package*/ DayInfo(String timestamp, Integer count, Integer uniques) { - this.timestamp = GitHub.parseDate(timestamp); - this.count = count; - this.uniques = uniques; - } - - /*package*/ DayInfo(Date timestamp, Integer count, Integer uniques) { + /*package*/ DailyInfo(String timestamp, Integer count, Integer uniques) { this.timestamp = timestamp; this.count = count; this.uniques = uniques; diff --git a/src/main/java/org/kohsuke/github/GHRepositoryViewTraffic.java b/src/main/java/org/kohsuke/github/GHRepositoryViewTraffic.java index 42c716cc6e..f2f1e5b440 100644 --- a/src/main/java/org/kohsuke/github/GHRepositoryViewTraffic.java +++ b/src/main/java/org/kohsuke/github/GHRepositoryViewTraffic.java @@ -1,6 +1,5 @@ package org.kohsuke.github; -import java.util.Date; import java.util.List; /** @@ -8,34 +7,30 @@ * * @see GHRepository#getViewTraffic() */ -public class GHRepositoryViewTraffic extends GHRepositoryTrafficInfo { - private List views; +public class GHRepositoryViewTraffic extends GHRepositoryTraffic { + private List views; /*package*/ GHRepositoryViewTraffic() { } - /*package*/ GHRepositoryViewTraffic(int count, int uniques, List views) { + /*package*/ GHRepositoryViewTraffic(int count, int uniques, List views) { super(count, uniques); this.views = views; } - public List getViews() { + public List getViews() { return views; } - public List getDailyInfo() { + public List getDailyInfo() { return getViews(); } - public static class Daily extends GHRepositoryTrafficInfo.DayInfo { - /*package*/ Daily() { + public static class DailyInfo extends GHRepositoryTraffic.DailyInfo { + /*package*/ DailyInfo() { } - /*package*/ Daily(String timestamp, int count, int uniques) { - super(timestamp, count, uniques); - } - - /*package*/ Daily(Date timestamp, int count, int uniques) { + /*package*/ DailyInfo(String timestamp, int count, int uniques) { super(timestamp, count, uniques); } } diff --git a/src/test/java/org/kohsuke/github/RepositoryTrafficTest.java b/src/test/java/org/kohsuke/github/RepositoryTrafficTest.java index 64864acfa2..3cc985b2c1 100644 --- a/src/test/java/org/kohsuke/github/RepositoryTrafficTest.java +++ b/src/test/java/org/kohsuke/github/RepositoryTrafficTest.java @@ -4,8 +4,6 @@ import org.apache.commons.io.IOUtils; import org.junit.Assert; import org.junit.Test; -import org.kohsuke.github.GHRepositoryCloneTraffic.DayInfo; -import org.kohsuke.github.GHRepositoryViewTraffic.Daily; import org.mockito.Mockito; import java.io.IOException; @@ -22,29 +20,29 @@ public class RepositoryTrafficTest { final private String login = "kohsuke", repositoryName = "github-api"; @SuppressWarnings("unchecked") - private void checkResponse(T expected, T actual){ + private void checkResponse(T expected, T actual){ Assert.assertEquals(expected.getCount(), actual.getCount()); Assert.assertEquals(expected.getUniques(), actual.getUniques()); - List expectedList = expected.getDailyInfo(); - List actualList = actual.getDailyInfo(); - Iterator expectedIt; - Iterator actualIt; + List expectedList = expected.getDailyInfo(); + List actualList = actual.getDailyInfo(); + Iterator expectedIt; + Iterator actualIt; Assert.assertEquals(expectedList.size(), actualList.size()); expectedIt = expectedList.iterator(); actualIt = actualList.iterator(); while(expectedIt.hasNext() && actualIt.hasNext()) { - GHRepositoryTrafficInfo.DayInfo expectedDayInfo = expectedIt.next(); - GHRepositoryTrafficInfo.DayInfo actualDayInfo = actualIt.next(); - Assert.assertEquals(expectedDayInfo.getCount(), actualDayInfo.getCount()); - Assert.assertEquals(expectedDayInfo.getUniques(), actualDayInfo.getUniques()); - Assert.assertEquals(expectedDayInfo.getTimestamp(), actualDayInfo.getTimestamp()); + DailyInfo expectedDailyInfo = expectedIt.next(); + DailyInfo actualDailyInfo = actualIt.next(); + Assert.assertEquals(expectedDailyInfo.getCount(), actualDailyInfo.getCount()); + Assert.assertEquals(expectedDailyInfo.getUniques(), actualDailyInfo.getUniques()); + Assert.assertEquals(expectedDailyInfo.getTimestamp(), actualDailyInfo.getTimestamp()); } } - private void testTraffic(T expectedResult) throws IOException{ + private void testTraffic(T expectedResult) throws IOException{ SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); ObjectMapper mapper = new ObjectMapper().setDateFormat(dateFormat); @@ -101,21 +99,21 @@ public void testGetViews() throws IOException{ 21523359, 65534, Arrays.asList( - new Daily("2016-10-10T00:00:00Z", 3, 2), - new Daily("2016-10-11T00:00:00Z", 9, 4), - new Daily("2016-10-12T00:00:00Z", 27, 8), - new Daily("2016-10-13T00:00:00Z", 81, 16), - new Daily("2016-10-14T00:00:00Z", 243, 32), - new Daily("2016-10-15T00:00:00Z", 729, 64), - new Daily("2016-10-16T00:00:00Z", 2187, 128), - new Daily("2016-10-17T00:00:00Z", 6561, 256), - new Daily("2016-10-18T00:00:00Z", 19683, 512), - new Daily("2016-10-19T00:00:00Z", 59049, 1024), - new Daily("2016-10-20T00:00:00Z", 177147, 2048), - new Daily("2016-10-21T00:00:00Z", 531441, 4096), - new Daily("2016-10-22T00:00:00Z", 1594323, 8192), - new Daily("2016-10-23T00:00:00Z", 4782969, 16384), - new Daily("2016-10-24T00:00:00Z", 14348907, 32768) + new GHRepositoryViewTraffic.DailyInfo("2016-10-10T00:00:00Z", 3, 2), + new GHRepositoryViewTraffic.DailyInfo("2016-10-11T00:00:00Z", 9, 4), + new GHRepositoryViewTraffic.DailyInfo("2016-10-12T00:00:00Z", 27, 8), + new GHRepositoryViewTraffic.DailyInfo("2016-10-13T00:00:00Z", 81, 16), + new GHRepositoryViewTraffic.DailyInfo("2016-10-14T00:00:00Z", 243, 32), + new GHRepositoryViewTraffic.DailyInfo("2016-10-15T00:00:00Z", 729, 64), + new GHRepositoryViewTraffic.DailyInfo("2016-10-16T00:00:00Z", 2187, 128), + new GHRepositoryViewTraffic.DailyInfo("2016-10-17T00:00:00Z", 6561, 256), + new GHRepositoryViewTraffic.DailyInfo("2016-10-18T00:00:00Z", 19683, 512), + new GHRepositoryViewTraffic.DailyInfo("2016-10-19T00:00:00Z", 59049, 1024), + new GHRepositoryViewTraffic.DailyInfo("2016-10-20T00:00:00Z", 177147, 2048), + new GHRepositoryViewTraffic.DailyInfo("2016-10-21T00:00:00Z", 531441, 4096), + new GHRepositoryViewTraffic.DailyInfo("2016-10-22T00:00:00Z", 1594323, 8192), + new GHRepositoryViewTraffic.DailyInfo("2016-10-23T00:00:00Z", 4782969, 16384), + new GHRepositoryViewTraffic.DailyInfo("2016-10-24T00:00:00Z", 14348907, 32768) ) ); testTraffic(expectedResult); @@ -127,21 +125,21 @@ public void testGetClones() throws IOException{ 1500, 455, Arrays.asList( - new DayInfo("2016-10-10T00:00:00Z", 10,3), - new DayInfo("2016-10-11T00:00:00Z", 20,6), - new DayInfo("2016-10-12T00:00:00Z", 30,5), - new DayInfo("2016-10-13T00:00:00Z", 40,7), - new DayInfo("2016-10-14T00:00:00Z", 50,11), - new DayInfo("2016-10-15T00:00:00Z", 60,12), - new DayInfo("2016-10-16T00:00:00Z", 70,19), - new DayInfo("2016-10-17T00:00:00Z", 170,111), - new DayInfo("2016-10-18T00:00:00Z", 180,70), - new DayInfo("2016-10-19T00:00:00Z", 190,10), - new DayInfo("2016-10-20T00:00:00Z", 200,18), - new DayInfo("2016-10-21T00:00:00Z", 210,8), - new DayInfo("2016-10-22T00:00:00Z", 220,168), - new DayInfo("2016-10-23T00:00:00Z", 5,2), - new DayInfo("2016-10-24T00:00:00Z", 45,5) + new GHRepositoryCloneTraffic.DailyInfo("2016-10-10T00:00:00Z", 10,3), + new GHRepositoryCloneTraffic.DailyInfo("2016-10-11T00:00:00Z", 20,6), + new GHRepositoryCloneTraffic.DailyInfo("2016-10-12T00:00:00Z", 30,5), + new GHRepositoryCloneTraffic.DailyInfo("2016-10-13T00:00:00Z", 40,7), + new GHRepositoryCloneTraffic.DailyInfo("2016-10-14T00:00:00Z", 50,11), + new GHRepositoryCloneTraffic.DailyInfo("2016-10-15T00:00:00Z", 60,12), + new GHRepositoryCloneTraffic.DailyInfo("2016-10-16T00:00:00Z", 70,19), + new GHRepositoryCloneTraffic.DailyInfo("2016-10-17T00:00:00Z", 170,111), + new GHRepositoryCloneTraffic.DailyInfo("2016-10-18T00:00:00Z", 180,70), + new GHRepositoryCloneTraffic.DailyInfo("2016-10-19T00:00:00Z", 190,10), + new GHRepositoryCloneTraffic.DailyInfo("2016-10-20T00:00:00Z", 200,18), + new GHRepositoryCloneTraffic.DailyInfo("2016-10-21T00:00:00Z", 210,8), + new GHRepositoryCloneTraffic.DailyInfo("2016-10-22T00:00:00Z", 220,168), + new GHRepositoryCloneTraffic.DailyInfo("2016-10-23T00:00:00Z", 5,2), + new GHRepositoryCloneTraffic.DailyInfo("2016-10-24T00:00:00Z", 45,5) ) ); testTraffic(expectedResult); From e6ad9feb84e89f4722ffbb25b3548d6ae213a6a1 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 12:05:39 -0700 Subject: [PATCH 283/390] Keeping Findbugs happy --- src/main/java/org/kohsuke/github/GHTreeBuilder.java | 3 +++ src/test/java/org/kohsuke/github/RepositoryTrafficTest.java | 1 + 2 files changed, 4 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHTreeBuilder.java b/src/main/java/org/kohsuke/github/GHTreeBuilder.java index cffbc8eafd..122c5775b5 100644 --- a/src/main/java/org/kohsuke/github/GHTreeBuilder.java +++ b/src/main/java/org/kohsuke/github/GHTreeBuilder.java @@ -1,5 +1,7 @@ package org.kohsuke.github; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -14,6 +16,7 @@ public class GHTreeBuilder { private final List treeEntries = new ArrayList(); + @SuppressFBWarnings("URF_UNREAD_FIELD") private static final class TreeEntry { private final String path; private final String mode; diff --git a/src/test/java/org/kohsuke/github/RepositoryTrafficTest.java b/src/test/java/org/kohsuke/github/RepositoryTrafficTest.java index 3cc985b2c1..b1f13e6c97 100644 --- a/src/test/java/org/kohsuke/github/RepositoryTrafficTest.java +++ b/src/test/java/org/kohsuke/github/RepositoryTrafficTest.java @@ -4,6 +4,7 @@ import org.apache.commons.io.IOUtils; import org.junit.Assert; import org.junit.Test; +import org.kohsuke.github.GHRepositoryTraffic.DailyInfo; import org.mockito.Mockito; import java.io.IOException; From f721e053f111f112fdf4de95afb250026d838edf Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 12:11:36 -0700 Subject: [PATCH 284/390] Added convenience connector for OkHttp3 Note that the existing one needs to be kept for compatibility with OkHttp2 --- pom.xml | 6 ++++ .../github/extras/OkHttp3Connector.java | 32 +++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 src/main/java/org/kohsuke/github/extras/OkHttp3Connector.java diff --git a/pom.xml b/pom.xml index 9b11b977f3..2258760f43 100644 --- a/pom.xml +++ b/pom.xml @@ -144,6 +144,12 @@ 2.7.5 true + + com.squareup.okhttp3 + okhttp-urlconnection + 3.4.0 + true + org.kohsuke wordnet-random-name diff --git a/src/main/java/org/kohsuke/github/extras/OkHttp3Connector.java b/src/main/java/org/kohsuke/github/extras/OkHttp3Connector.java new file mode 100644 index 0000000000..d2fd8c6978 --- /dev/null +++ b/src/main/java/org/kohsuke/github/extras/OkHttp3Connector.java @@ -0,0 +1,32 @@ +package org.kohsuke.github.extras; + +import okhttp3.OkHttpClient; +import okhttp3.OkUrlFactory; +import org.kohsuke.github.HttpConnector; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; + +/** + * {@link HttpConnector} for {@link OkHttpClient}. + * + * Unlike {@link #DEFAULT}, OkHttp does response caching. + * Making a conditional request against GitHubAPI and receiving a 304 + * response does not count against the rate limit. + * See http://developer.github.com/v3/#conditional-requests + * + * @author Roberto Tyley + * @author Kohsuke Kawaguchi + */ +public class OkHttp3Connector implements HttpConnector { + private final OkUrlFactory urlFactory; + + public OkHttp3Connector(OkUrlFactory urlFactory) { + this.urlFactory = urlFactory; + } + + public HttpURLConnection connect(URL url) throws IOException { + return urlFactory.open(url); + } +} From fe2af19e42c818560e49d8c74282fc8d5f62e076 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 12:15:21 -0700 Subject: [PATCH 285/390] Unused constant --- src/main/java/org/kohsuke/github/Previews.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/Previews.java b/src/main/java/org/kohsuke/github/Previews.java index 3b7eeb5939..238b062b8b 100644 --- a/src/main/java/org/kohsuke/github/Previews.java +++ b/src/main/java/org/kohsuke/github/Previews.java @@ -8,5 +8,4 @@ static final String DRAX = "application/vnd.github.drax-preview+json"; static final String SQUIRREL_GIRL = "application/vnd.github.squirrel-girl-preview"; static final String KORRA = "application/vnd.github.korra-preview"; - static final String POLARIS = "application/vnd.github.polaris-preview"; } From 9012820c0343240ac53fd2fbb5f1f8306d761be8 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 12:17:21 -0700 Subject: [PATCH 286/390] Massage the signature a bit. AFAICT sha and merge_method are not mutually exclusive. --- src/main/java/org/kohsuke/github/GHPullRequest.java | 13 +++++++------ .../org/kohsuke/github/extras/OkHttpConnector.java | 1 + .../java/org/kohsuke/github/PullRequestTest.java | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index 096adcf92e..4985f552cb 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -277,7 +277,7 @@ public GHPullRequestReviewComment createReviewComment(String body, String sha, S * Commit message. If null, the default one will be used. */ public void merge(String msg) throws IOException { - merge(msg,(String)null); + merge(msg,null); } /** @@ -291,7 +291,7 @@ public void merge(String msg) throws IOException { * 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"); + merge(msg, sha, null); } /** @@ -304,11 +304,12 @@ public void merge(String msg, String sha) throws IOException { * @param method * SHA that pull request head must match to allow merge. */ - public void merge(String msg, MergeMethod method) throws IOException { + public void merge(String msg, String sha, MergeMethod method) throws IOException { new Requester(root).method("PUT") - .with("commit_message",msg) - .with("merge_method",method) - .to(getApiRoute()+"/merge"); + .with("commit_message",msg) + .with("sha",sha) + .with("merge_method",method) + .to(getApiRoute()+"/merge"); } public enum MergeMethod{ MERGE, SQUASH, REBASE } diff --git a/src/main/java/org/kohsuke/github/extras/OkHttpConnector.java b/src/main/java/org/kohsuke/github/extras/OkHttpConnector.java index faa06b0d3b..b7bad2e971 100644 --- a/src/main/java/org/kohsuke/github/extras/OkHttpConnector.java +++ b/src/main/java/org/kohsuke/github/extras/OkHttpConnector.java @@ -30,3 +30,4 @@ public HttpURLConnection connect(URL url) throws IOException { return urlFactory.open(url); } } +GHPul \ No newline at end of file diff --git a/src/test/java/org/kohsuke/github/PullRequestTest.java b/src/test/java/org/kohsuke/github/PullRequestTest.java index ba8f087197..f90c83353d 100644 --- a/src/test/java/org/kohsuke/github/PullRequestTest.java +++ b/src/test/java/org/kohsuke/github/PullRequestTest.java @@ -78,7 +78,7 @@ public void testSquashMerge() throws Exception { Thread.sleep(1000); GHPullRequest p = getRepository().createPullRequest(name, name, "master", "## test squash"); Thread.sleep(1000); - p.merge("squash merge", GHPullRequest.MergeMethod.SQUASH); + p.merge("squash merge", null, GHPullRequest.MergeMethod.SQUASH); branchRef.delete(); } From 353f9bb809c68b0ffd56f205ee23f80afff82e15 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 12:23:40 -0700 Subject: [PATCH 287/390] pointless null check since the with method already does it --- .../java/org/kohsuke/github/GHReleaseBuilder.java | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHReleaseBuilder.java b/src/main/java/org/kohsuke/github/GHReleaseBuilder.java index b1daac956e..e427bdf8a5 100644 --- a/src/main/java/org/kohsuke/github/GHReleaseBuilder.java +++ b/src/main/java/org/kohsuke/github/GHReleaseBuilder.java @@ -21,9 +21,7 @@ public GHReleaseBuilder(GHRepository ghRepository, String tag) { * @param body The release notes body. */ public GHReleaseBuilder body(String body) { - if (body != null) { - builder.with("body", body); - } + builder.with("body", body); return this; } @@ -35,9 +33,7 @@ public GHReleaseBuilder body(String body) { * already exists. */ public GHReleaseBuilder commitish(String commitish) { - if (commitish != null) { - builder.with("target_commitish", commitish); - } + builder.with("target_commitish", commitish); return this; } @@ -56,9 +52,7 @@ public GHReleaseBuilder draft(boolean draft) { * @param name the name of the release */ public GHReleaseBuilder name(String name) { - if (name != null) { - builder.with("name", name); - } + builder.with("name", name); return this; } From d8f4bc739595dcf08205648342c52d04a56903e4 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 12:31:10 -0700 Subject: [PATCH 288/390] Added updater This solves #331 differently --- .../java/org/kohsuke/github/GHRelease.java | 14 ++-- .../org/kohsuke/github/GHReleaseUpdater.java | 81 +++++++++++++++++++ 2 files changed, 89 insertions(+), 6 deletions(-) create mode 100644 src/main/java/org/kohsuke/github/GHReleaseUpdater.java diff --git a/src/main/java/org/kohsuke/github/GHRelease.java b/src/main/java/org/kohsuke/github/GHRelease.java index 524bce70b4..a299add2c5 100644 --- a/src/main/java/org/kohsuke/github/GHRelease.java +++ b/src/main/java/org/kohsuke/github/GHRelease.java @@ -45,10 +45,12 @@ public boolean isDraft() { return draft; } + /** + * @deprecated + * Use {@link #update()} + */ public GHRelease setDraft(boolean draft) throws IOException { - edit("draft", draft); - this.draft = draft; - return this; + return update().draft(draft).update(); } public URL getHtmlUrl() { @@ -149,10 +151,10 @@ public void delete() throws IOException { } /** - * Edit this release. + * Updates this release via a builder. */ - private void edit(String key, Object value) throws IOException { - new Requester(root)._with(key, value).method("PATCH").to(owner.getApiTailUrl("releases/"+id)); + public GHReleaseUpdater update() { + return new GHReleaseUpdater(this); } private String getApiTailUrl(String end) { diff --git a/src/main/java/org/kohsuke/github/GHReleaseUpdater.java b/src/main/java/org/kohsuke/github/GHReleaseUpdater.java new file mode 100644 index 0000000000..a34a5b0bc2 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHReleaseUpdater.java @@ -0,0 +1,81 @@ +package org.kohsuke.github; + +import java.io.IOException; + +/** + * Modifies {@link GHRelease}. + * + * @author Kohsuke Kawaguchi + * @see GHRelease#update() + */ +public class GHReleaseUpdater { + private final GHRelease base; + private final Requester builder; + + GHReleaseUpdater(GHRelease base) { + this.base = base; + this.builder = new Requester(base.root); + } + + public GHReleaseUpdater tag(String tag) { + builder.with("tag_name",tag); + return this; + } + + /** + * @param body The release notes body. + */ + public GHReleaseUpdater body(String body) { + builder.with("body", body); + return this; + } + + /** + * Specifies the commitish value that determines where the Git tag is created from. Can be any branch or + * commit SHA. + * + * @param commitish Defaults to the repository’s default branch (usually "master"). Unused if the Git tag + * already exists. + */ + public GHReleaseUpdater commitish(String commitish) { + builder.with("target_commitish", commitish); + return this; + } + + /** + * Optional. + * + * @param draft {@code true} to create a draft (unpublished) release, {@code false} to create a published one. + * Default is {@code false}. + */ + public GHReleaseUpdater draft(boolean draft) { + builder.with("draft", draft); + return this; + } + + /** + * @param name the name of the release + */ + public GHReleaseUpdater name(String name) { + builder.with("name", name); + return this; + } + + /** + * Optional + * + * @param prerelease {@code true} to identify the release as a prerelease. {@code false} to identify the release + * as a full release. Default is {@code false}. + */ + public GHReleaseUpdater prerelease(boolean prerelease) { + builder.with("prerelease", prerelease); + return this; + } + + public GHRelease update() throws IOException { + return builder + .method("PATCH") + .to(base.owner.getApiTailUrl("releases/"+base.id), GHRelease.class).wrap(base.owner); + } + +} From 2d3557e049c8c365dcaf44991ba42d5a394668c4 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 12:44:12 -0700 Subject: [PATCH 289/390] Improved the intern logic if the user record does not exist yet, there's no need to fetch that eagerly, as they are fetched on demand via the populate() method. --- .../org/kohsuke/github/GHCommitPointer.java | 2 +- .../java/org/kohsuke/github/GHCommitStatus.java | 3 +-- .../java/org/kohsuke/github/GHDeployment.java | 3 +-- src/main/java/org/kohsuke/github/GHGist.java | 2 +- src/main/java/org/kohsuke/github/GHIssue.java | 17 ++++++++++------- .../java/org/kohsuke/github/GHMilestone.java | 2 +- src/main/java/org/kohsuke/github/GitHub.java | 17 +++++++++++++++-- 7 files changed, 30 insertions(+), 16 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHCommitPointer.java b/src/main/java/org/kohsuke/github/GHCommitPointer.java index 6b3f414f43..b6c347864e 100644 --- a/src/main/java/org/kohsuke/github/GHCommitPointer.java +++ b/src/main/java/org/kohsuke/github/GHCommitPointer.java @@ -40,7 +40,7 @@ public class GHCommitPointer { * the {@link #getRepository()}. */ public GHUser getUser() throws IOException { - if (user != null) return user.root.getUser(user.getLogin()); + if (user != null) return user.root.intern(user); return user; } diff --git a/src/main/java/org/kohsuke/github/GHCommitStatus.java b/src/main/java/org/kohsuke/github/GHCommitStatus.java index f71be99622..63a62ae8d0 100644 --- a/src/main/java/org/kohsuke/github/GHCommitStatus.java +++ b/src/main/java/org/kohsuke/github/GHCommitStatus.java @@ -47,8 +47,7 @@ public String getDescription() { } public GHUser getCreator() throws IOException { - if (creator != null) return creator.root.getUser(creator.getLogin()); - return creator; + return root.intern(creator); } public String getContext() { diff --git a/src/main/java/org/kohsuke/github/GHDeployment.java b/src/main/java/org/kohsuke/github/GHDeployment.java index ff8b4d6afc..0cef10ee52 100644 --- a/src/main/java/org/kohsuke/github/GHDeployment.java +++ b/src/main/java/org/kohsuke/github/GHDeployment.java @@ -42,8 +42,7 @@ public String getEnvironment() { return environment; } public GHUser getCreator() throws IOException { - if(creator != null) return root.getUser(creator.getLogin()); - return creator; + return root.intern(creator); } public String getRef() { return ref; diff --git a/src/main/java/org/kohsuke/github/GHGist.java b/src/main/java/org/kohsuke/github/GHGist.java index e0954175d0..a9bf3fef42 100644 --- a/src/main/java/org/kohsuke/github/GHGist.java +++ b/src/main/java/org/kohsuke/github/GHGist.java @@ -39,7 +39,7 @@ public class GHGist extends GHObject { * User that owns this Gist. */ public GHUser getOwner() throws IOException { - return root.getUser(owner.getLogin()); + return root.intern(owner); } public String getForksUrl() { diff --git a/src/main/java/org/kohsuke/github/GHIssue.java b/src/main/java/org/kohsuke/github/GHIssue.java index 9a3b31f11b..6b416ca1d3 100644 --- a/src/main/java/org/kohsuke/github/GHIssue.java +++ b/src/main/java/org/kohsuke/github/GHIssue.java @@ -289,8 +289,7 @@ protected String getIssuesApiRoute() { } public GHUser getAssignee() throws IOException { - if (assignee != null) return owner.root.getUser(assignee.getLogin()); - return assignee; + return root.intern(assignee); } public List getAssignees() { @@ -301,7 +300,7 @@ public List getAssignees() { * User who submitted the issue. */ public GHUser getUser() throws IOException { - return owner.root.getUser(user.getLogin()); + return root.intern(user); } /** @@ -314,10 +313,14 @@ public GHUser getUser() throws IOException { */ public GHUser getClosedBy() throws IOException { if(!"closed".equals(state)) return null; - if(closed_by != null) return owner.root.getUser(closed_by.getLogin());; - - //TODO closed_by = owner.getIssue(number).getClosed_by(); - return closed_by; + + //TODO + /* + if (closed_by==null) { + closed_by = owner.getIssue(number).getClosed_by(); + } + */ + return root.intern(closed_by); } public int getCommentsCount(){ diff --git a/src/main/java/org/kohsuke/github/GHMilestone.java b/src/main/java/org/kohsuke/github/GHMilestone.java index 950dea2574..50ad549e82 100644 --- a/src/main/java/org/kohsuke/github/GHMilestone.java +++ b/src/main/java/org/kohsuke/github/GHMilestone.java @@ -28,7 +28,7 @@ public GHRepository getOwner() { } public GHUser getCreator() throws IOException { - return root.getUser(creator.getLogin()); + return root.intern(creator); } public Date getDueOn() { diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index bde74b1262..201ccaff33 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -48,6 +48,7 @@ import java.util.Set; import java.util.TimeZone; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.logging.Logger; import javax.annotation.CheckForNull; import javax.annotation.Nonnull; @@ -80,8 +81,8 @@ public class GitHub { */ /*package*/ final String encodedAuthorization; - private final Map users; - private final Map orgs; + private final ConcurrentMap users; + private final ConcurrentMap orgs; // Cache of myself object. private GHMyself myself; private final String apiUrl; @@ -647,6 +648,18 @@ public boolean isCredentialValid() throws IOException { } } + /*package*/ GHUser intern(GHUser user) throws IOException { + if (user==null) return user; + + // if we already have this user in our map, use it + GHUser u = users.get(user.getLogin()); + if (u!=null) return u; + + // if not, remember this new user + users.putIfAbsent(user.getLogin(),user); + return user; + } + private static class GHApiInfo { private String rate_limit_url; From 40fb38a9ba98fc6de8defd8f3fbb497ea1e17753 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 12:45:58 -0700 Subject: [PATCH 290/390] Window focus problem --- src/main/java/org/kohsuke/github/extras/OkHttpConnector.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/extras/OkHttpConnector.java b/src/main/java/org/kohsuke/github/extras/OkHttpConnector.java index b7bad2e971..faa06b0d3b 100644 --- a/src/main/java/org/kohsuke/github/extras/OkHttpConnector.java +++ b/src/main/java/org/kohsuke/github/extras/OkHttpConnector.java @@ -30,4 +30,3 @@ public HttpURLConnection connect(URL url) throws IOException { return urlFactory.open(url); } } -GHPul \ No newline at end of file From 6178d3889546e7eb5de5f4bdb3ab17d0e6c16f5f Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 12:47:18 -0700 Subject: [PATCH 291/390] connector usage is unsynchronized --- 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 e248372ad1..62c1b4e80c 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -269,7 +269,7 @@ public String getApiUrl() { /** * Sets the custom connector used to make requests to GitHub. */ - public synchronized void setConnector(HttpConnector connector) { + public void setConnector(HttpConnector connector) { this.connector = connector; } From 92caf986835b711cd602792c5faa47bed99970c6 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 12:57:52 -0700 Subject: [PATCH 292/390] Reverting java1.6 change which I assume is accidental. Not that I really care about Java5 but I think that change should be done separatel & intentionally --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 9f372d703d..fe8e0faff7 100644 --- a/pom.xml +++ b/pom.xml @@ -41,13 +41,13 @@ org.codehaus.mojo.signature - java16 + java15 1.0 - ensure-java-1.6-class-library + ensure-java-1.5-class-library test check From 692dccf110ceb2281c1d8ac887b6a66c70387f3a Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 13:03:18 -0700 Subject: [PATCH 293/390] Massaging the change a bit --- .../GHFileNotFoundException.java | 4 +-- .../github/{exception => }/GHIOException.java | 12 +++---- .../java/org/kohsuke/github/GHObject.java | 16 +++++++-- .../java/org/kohsuke/github/Requester.java | 34 ++++++------------- .../java/org/kohsuke/github/GHHookTest.java | 1 - 5 files changed, 33 insertions(+), 34 deletions(-) rename src/main/java/org/kohsuke/github/{exception => }/GHFileNotFoundException.java (85%) rename src/main/java/org/kohsuke/github/{exception => }/GHIOException.java (66%) diff --git a/src/main/java/org/kohsuke/github/exception/GHFileNotFoundException.java b/src/main/java/org/kohsuke/github/GHFileNotFoundException.java similarity index 85% rename from src/main/java/org/kohsuke/github/exception/GHFileNotFoundException.java rename to src/main/java/org/kohsuke/github/GHFileNotFoundException.java index 27606de595..9f4b37c560 100644 --- a/src/main/java/org/kohsuke/github/exception/GHFileNotFoundException.java +++ b/src/main/java/org/kohsuke/github/GHFileNotFoundException.java @@ -1,4 +1,4 @@ -package org.kohsuke.github.exception; +package org.kohsuke.github; import javax.annotation.CheckForNull; import java.io.FileNotFoundException; @@ -27,7 +27,7 @@ public Map> getResponseHeaderFields() { return responseHeaderFields; } - public GHFileNotFoundException withResponseHeaderFields(HttpURLConnection urlConnection) { + GHFileNotFoundException withResponseHeaderFields(HttpURLConnection urlConnection) { this.responseHeaderFields = urlConnection.getHeaderFields(); return this; } diff --git a/src/main/java/org/kohsuke/github/exception/GHIOException.java b/src/main/java/org/kohsuke/github/GHIOException.java similarity index 66% rename from src/main/java/org/kohsuke/github/exception/GHIOException.java rename to src/main/java/org/kohsuke/github/GHIOException.java index 7bb614092e..5cdc9e541a 100644 --- a/src/main/java/org/kohsuke/github/exception/GHIOException.java +++ b/src/main/java/org/kohsuke/github/GHIOException.java @@ -1,4 +1,4 @@ -package org.kohsuke.github.exception; +package org.kohsuke.github; import javax.annotation.CheckForNull; import java.io.IOException; @@ -13,7 +13,7 @@ * @author Kanstantsin Shautsou */ public class GHIOException extends IOException { - protected Map> responceHeaderFields; + protected Map> responseHeaderFields; public GHIOException() { } @@ -31,12 +31,12 @@ public GHIOException(Throwable cause) { } @CheckForNull - public Map> getResponceHeaderFields() { - return responceHeaderFields; + public Map> getResponseHeaderFields() { + return responseHeaderFields; } - public GHIOException withResponceHeaderFields(HttpURLConnection urlConnection) { - this.responceHeaderFields = urlConnection.getHeaderFields(); + GHIOException withResponseHeaderFields(HttpURLConnection urlConnection) { + this.responseHeaderFields = urlConnection.getHeaderFields(); return this; } } diff --git a/src/main/java/org/kohsuke/github/GHObject.java b/src/main/java/org/kohsuke/github/GHObject.java index 3a1cde1908..96e41a2559 100644 --- a/src/main/java/org/kohsuke/github/GHObject.java +++ b/src/main/java/org/kohsuke/github/GHObject.java @@ -19,7 +19,9 @@ @SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD"}, justification = "JSON API") public abstract class GHObject { - // not data but information related to data from responce + /** + * Capture response HTTP headers on the state object. + */ protected Map> responseHeaderFields; protected String url; @@ -30,7 +32,17 @@ public abstract class GHObject { /*package*/ GHObject() { } - @CheckForNull + /** + * Returns the HTTP response headers given along with the state of this object. + * + *

+ * Some of the HTTP headers have nothing to do with the object, for example "Cache-Control" + * and others are different depending on how this object was retrieved. + * + * This method was added as a kind of hack to allow the caller to retrieve OAuth scopes and such. + * Use with caution. The method might be removed in the future. + */ + @CheckForNull @Deprecated public Map> getResponseHeaderFields() { return responseHeaderFields; } diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index 64aefe68fe..57ce89f0b1 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -26,8 +26,6 @@ import com.fasterxml.jackson.databind.JsonMappingException; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.apache.commons.io.IOUtils; -import org.kohsuke.github.exception.GHFileNotFoundException; -import org.kohsuke.github.exception.GHIOException; import java.io.FileNotFoundException; import java.io.IOException; @@ -274,7 +272,7 @@ private T _to(String tailApiUrl, Class type, T instance) throws IOExcepti if (nextLinkMatcher.find()) { final String link = nextLinkMatcher.group(1); T nextResult = _to(link, type, instance); - injectInResult(nextResult); + setResponseHeaders(nextResult); final int resultLength = Array.getLength(result); final int nextResultLength = Array.getLength(nextResult); T concatResult = (T) Array.newInstance(type.getComponentType(), resultLength + nextResultLength); @@ -284,8 +282,7 @@ private T _to(String tailApiUrl, Class type, T instance) throws IOExcepti } } } - injectInResult(result); - return result; + return setResponseHeaders(result); } catch (IOException e) { handleApiError(e); } finally { @@ -605,16 +602,12 @@ private T parse(Class type, T instance) throws IOException { String data = IOUtils.toString(r); if (type!=null) try { - final T readValue = MAPPER.readValue(data, type); - injectInResult(readValue); - return readValue; + return setResponseHeaders(MAPPER.readValue(data, type)); } catch (JsonMappingException e) { throw (IOException)new IOException("Failed to deserialize " +data).initCause(e); } if (instance!=null) { - final T readValue = MAPPER.readerForUpdating(instance).readValue(data); - injectInResult(readValue); - return readValue; + return setResponseHeaders(MAPPER.readerForUpdating(instance).readValue(data)); } return null; } catch (FileNotFoundException e) { @@ -628,24 +621,19 @@ private T parse(Class type, T instance) throws IOException { } } - private void injectInResult(T readValue) { + private T setResponseHeaders(T readValue) { if (readValue instanceof GHObject[]) { for (GHObject ghObject : (GHObject[]) readValue) { - injectInResult(ghObject); + setResponseHeaders(ghObject); } } else if (readValue instanceof GHObject) { - injectInResult((GHObject) readValue); + setResponseHeaders((GHObject) readValue); } + return readValue; } - private void injectInResult(GHObject readValue) { - try { - final Field field = GHObject.class.getDeclaredField("responseHeaderFields"); - field.setAccessible(true); - field.set(readValue, uc.getHeaderFields()); - } catch (NoSuchFieldException ignore) { - } catch (IllegalAccessException ignore) { - } + private void setResponseHeaders(GHObject readValue) { + readValue.responseHeaderFields = uc.getHeaderFields(); } /** @@ -700,7 +688,7 @@ private InputStream wrapStream(InputStream in) throws IOException { HttpException http = (HttpException) e; throw (IOException) new HttpException(error, http.getResponseCode(), http.getResponseMessage(), http.getUrl(), e); } else { - throw (IOException) new GHIOException(error).withResponceHeaderFields(uc).initCause(e); + throw (IOException) new GHIOException(error).withResponseHeaderFields(uc).initCause(e); } } else { throw e; diff --git a/src/test/java/org/kohsuke/github/GHHookTest.java b/src/test/java/org/kohsuke/github/GHHookTest.java index 2cbab48cb7..b27484b5e5 100644 --- a/src/test/java/org/kohsuke/github/GHHookTest.java +++ b/src/test/java/org/kohsuke/github/GHHookTest.java @@ -3,7 +3,6 @@ import org.apache.commons.lang.StringUtils; import org.junit.Ignore; import org.junit.Test; -import org.kohsuke.github.exception.GHFileNotFoundException; import java.io.IOException; import java.util.Arrays; From 60bfea2d3b46a423aa0b3d7d43944b9acfdfef50 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 13:22:16 -0700 Subject: [PATCH 294/390] Bug fix --- src/main/java/org/kohsuke/github/GHEventPayload.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHEventPayload.java b/src/main/java/org/kohsuke/github/GHEventPayload.java index 8f5799430f..3d23973fd5 100644 --- a/src/main/java/org/kohsuke/github/GHEventPayload.java +++ b/src/main/java/org/kohsuke/github/GHEventPayload.java @@ -78,7 +78,7 @@ void wrapUp(GitHub root) { throw new IllegalStateException("Expected pull_request payload, but got something else. Maybe we've got another type of event?"); if (repository!=null) { repository.wrap(root); - pull_request.wrap(repository); + pull_request.wrapUp(repository); } else { pull_request.wrapUp(root); } From 47409a9a999eecd5507837b602a6e1f342894568 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 13:28:31 -0700 Subject: [PATCH 295/390] [maven-release-plugin] prepare release github-api-1.89 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index a1074f7024..fffadeffd9 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.89-SNAPSHOT + 1.89 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - HEAD + github-api-1.89 From d4404713a830b01a6b04536d44f7341e3eccde2d Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 13:28:40 -0700 Subject: [PATCH 296/390] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index fffadeffd9..ff898cccd0 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.89 + 1.90-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - github-api-1.89 + HEAD From b443e866f9fd6c8ebff390562ca4304d79aaf71c Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 9 Sep 2017 20:38:40 -0700 Subject: [PATCH 297/390] Added lock/unlock op and additional properties Issue #355 --- src/main/java/org/kohsuke/github/GHIssue.java | 13 +++++++++++++ .../java/org/kohsuke/github/GHPullRequest.java | 14 ++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHIssue.java b/src/main/java/org/kohsuke/github/GHIssue.java index 6b416ca1d3..117c06f8d8 100644 --- a/src/main/java/org/kohsuke/github/GHIssue.java +++ b/src/main/java/org/kohsuke/github/GHIssue.java @@ -68,6 +68,7 @@ public class GHIssue extends GHObject implements Reactable{ protected GHIssue.PullRequest pull_request; protected GHMilestone milestone; protected GHUser closed_by; + protected boolean locked; /** * @deprecated use {@link GHLabel} @@ -129,6 +130,10 @@ public String getTitle() { return title; } + public boolean isLocked() { + return locked; + } + public GHIssueState getState() { return Enum.valueOf(GHIssueState.class, state.toUpperCase(Locale.ENGLISH)); } @@ -148,6 +153,14 @@ public URL getApiURL(){ return GitHub.parseURL(url); } + public void lock() throws IOException { + new Requester(root).method("PUT").to(getApiRoute()+"/lock"); + } + + public void unlock() throws IOException { + new Requester(root).method("PUT").to(getApiRoute()+"/lock"); + } + /** * Updates the issue by adding a comment. * diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index 6e1a5d90e5..9342623829 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -50,8 +50,8 @@ public class GHPullRequest extends GHIssue { // details that are only available when obtained from ID private GHUser merged_by; - private int review_comments, additions; - private boolean merged; + private int review_comments, additions, commits; + private boolean merged, maintainer_can_modify; private Boolean mergeable; private int deletions; private String mergeable_state; @@ -167,11 +167,21 @@ public int getAdditions() throws IOException { return additions; } + public int getCommits() throws IOException { + populate(); + return commits; + } + public boolean isMerged() throws IOException { populate(); return merged; } + public boolean canMaintainerModify() throws IOException { + populate(); + return maintainer_can_modify; + } + public Boolean getMergeable() throws IOException { populate(); return mergeable; From 09c2b39530d3f128da1a2393df7f345fa50c61f0 Mon Sep 17 00:00:00 2001 From: Jesse Glick Date: Wed, 13 Sep 2017 15:14:42 -0400 Subject: [PATCH 298/390] bridge-method-annotation should be an optional dep. --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index ff898cccd0..50d535cf67 100644 --- a/pom.xml +++ b/pom.xml @@ -131,6 +131,7 @@ com.infradna.tool bridge-method-annotation 1.14 + true org.kohsuke.stapler From ae1ec8b5580c33f7fc6bf19a580541980969ee35 Mon Sep 17 00:00:00 2001 From: Anton Zagorskii Date: Wed, 20 Sep 2017 13:22:30 +0100 Subject: [PATCH 299/390] Roles for team members --- src/main/java/org/kohsuke/github/GHTeam.java | 26 ++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHTeam.java b/src/main/java/org/kohsuke/github/GHTeam.java index ae950aed70..a2f9a87ae4 100644 --- a/src/main/java/org/kohsuke/github/GHTeam.java +++ b/src/main/java/org/kohsuke/github/GHTeam.java @@ -18,6 +18,12 @@ public class GHTeam { protected /*final*/ GHOrganization org; + /** Member's role in a team */ + public enum ROLE { + MEMBER, // A normal member of the team + MAINTAINER // Able to add/remove other team members, promote other team members to team maintainer, and edit the team's name and description. + }; + /*package*/ GHTeam wrapUp(GHOrganization owner) { this.org = owner; return this; @@ -116,6 +122,22 @@ public void add(GHUser u) throws IOException { org.root.retrieve().method("PUT").to(api("/memberships/" + u.getLogin()), null); } + /** + * Adds a member to the team + * + * The user will be invited to the organization if required. + * + * @param user github user + * @param role role for the new member + * + * @throws IOException + */ + public void add(GHUser user, ROLE role) throws IOException { + org.root.retrieve().method("PUT") + .with("role", role.name()) + .to(api("/memberships/" + user.getLogin()), null); + } + /** * Removes a member to the team. */ @@ -129,7 +151,7 @@ public void add(GHRepository r) throws IOException { public void add(GHRepository r, GHOrganization.Permission permission) throws IOException { org.root.retrieve().method("PUT") - .with("permission",permission) + .with("permission", permission) .to(api("/repos/" + r.getOwnerName() + '/' + r.getName()), null); } @@ -145,7 +167,7 @@ public void delete() throws IOException { } private String api(String tail) { - return "/teams/"+id+tail; + return "/teams/" + id + tail; } public GHOrganization getOrganization() { From 0f81d1dbb35f4a7a34791c188ef6abd256025564 Mon Sep 17 00:00:00 2001 From: Matt Nelson Date: Thu, 5 Oct 2017 18:14:15 -0500 Subject: [PATCH 300/390] Add support for pr review/review comment events --- .../org/kohsuke/github/GHEventPayload.java | 89 +++++++++++++++++++ .../kohsuke/github/GHPullRequestReview.java | 8 +- .../github/GHPullRequestReviewState.java | 2 +- .../kohsuke/github/GHEventPayloadTest.java | 60 +++++++++++-- 4 files changed, 148 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHEventPayload.java b/src/main/java/org/kohsuke/github/GHEventPayload.java index 3d23973fd5..b01b32e432 100644 --- a/src/main/java/org/kohsuke/github/GHEventPayload.java +++ b/src/main/java/org/kohsuke/github/GHEventPayload.java @@ -85,6 +85,95 @@ void wrapUp(GitHub root) { } } + + /** + * A review was added to a pull request + * + * @see authoritative source + */ + public static class PullRequestReview extends GHEventPayload { + private String action; + private GHPullRequestReview review; + private GHPullRequest pull_request; + private GHRepository repository; + + public String getAction() { + return action; + } + + public GHPullRequestReview getReview() { + return review; + } + + public GHPullRequest getPullRequest() { + return pull_request; + } + + public GHRepository getRepository() { + return repository; + } + + @Override + void wrapUp(GitHub root) { + super.wrapUp(root); + if (review==null) + throw new IllegalStateException("Expected pull_request_review payload, but got something else. Maybe we've got another type of event?"); + + review.wrapUp(pull_request); + + if (repository!=null) { + repository.wrap(root); + pull_request.wrapUp(repository); + } else { + pull_request.wrapUp(root); + } + } + } + + /** + * A review comment was added to a pull request + * + * @see authoritative source + */ + public static class PullRequestReviewComment extends GHEventPayload { + private String action; + private GHPullRequestReviewComment comment; + private GHPullRequest pull_request; + private GHRepository repository; + + public String getAction() { + return action; + } + + public GHPullRequestReviewComment getComment() { + return comment; + } + + public GHPullRequest getPullRequest() { + return pull_request; + } + + public GHRepository getRepository() { + return repository; + } + + @Override + void wrapUp(GitHub root) { + super.wrapUp(root); + if (comment==null) + throw new IllegalStateException("Expected pull_request_review_comment payload, but got something else. Maybe we've got another type of event?"); + + comment.wrapUp(pull_request); + + if (repository!=null) { + repository.wrap(root); + pull_request.wrapUp(repository); + } else { + pull_request.wrapUp(root); + } + } + } + /** * A comment was added to an issue * diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReview.java b/src/main/java/org/kohsuke/github/GHPullRequestReview.java index d7afe59aad..8aa00c4b54 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestReview.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestReview.java @@ -40,7 +40,7 @@ public class GHPullRequestReview extends GHObject { private String body; private GHUser user; private String commit_id; - private GHPullRequestReviewState state; + private String state; /*package*/ GHPullRequestReview wrapUp(GHPullRequest owner) { this.owner = owner; @@ -73,7 +73,7 @@ public String getCommitId() { } public GHPullRequestReviewState getState() { - return state; + return GHPullRequestReviewState.valueOf(state.toUpperCase()); } @Override @@ -97,7 +97,7 @@ public void submit(String body, GHPullRequestReviewState event) throws IOExcepti .withPreview("application/vnd.github.black-cat-preview+json") .to(getApiRoute()+"/events",this); this.body = body; - this.state = event; + this.state = event.name(); } /** @@ -121,7 +121,7 @@ public void dismiss(String message) throws IOException { .with("message", message) .withPreview(BLACK_CAT) .to(getApiRoute()+"/dismissals"); - state = GHPullRequestReviewState.DISMISSED; + state = GHPullRequestReviewState.DISMISSED.name(); } /** diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReviewState.java b/src/main/java/org/kohsuke/github/GHPullRequestReviewState.java index fca3fabfb3..e909e54450 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestReviewState.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestReviewState.java @@ -3,7 +3,7 @@ public enum GHPullRequestReviewState { PENDING(null), APPROVED("APPROVE"), - REQUEST_CHANGES("REQUEST_CHANGES"), + CHANGES_REQUESTED("REQUEST_CHANGES"), COMMENTED("COMMENT"), DISMISSED(null); diff --git a/src/test/java/org/kohsuke/github/GHEventPayloadTest.java b/src/test/java/org/kohsuke/github/GHEventPayloadTest.java index 07758d1a03..d2ff30012f 100644 --- a/src/test/java/org/kohsuke/github/GHEventPayloadTest.java +++ b/src/test/java/org/kohsuke/github/GHEventPayloadTest.java @@ -187,13 +187,61 @@ public void pull_request() throws Exception { assertThat(event.getSender().getLogin(), is("baxterthehacker")); } -// TODO implement support classes and write test -// @Test -// public void pull_request_review() throws Exception {} + @Test + public void pull_request_review() throws Exception { + GHEventPayload.PullRequestReview event = + GitHub.offline().parseEventPayload(payload.asReader(), GHEventPayload.PullRequestReview.class); + assertThat(event.getAction(), is("submitted")); + + assertThat(event.getReview().getId(), is(2626884)); + assertThat(event.getReview().getBody(), is("Looks great!")); + assertThat(event.getReview().getState(), is(GHPullRequestReviewState.APPROVED)); + + assertThat(event.getPullRequest().getNumber(), is(8)); + assertThat(event.getPullRequest().getTitle(), is("Add a README description")); + assertThat(event.getPullRequest().getBody(), is("Just a few more details")); + assertThat(event.getPullRequest().getUser().getLogin(), is("skalnik")); + assertThat(event.getPullRequest().getHead().getUser().getLogin(), is("skalnik")); + assertThat(event.getPullRequest().getHead().getRef(), is("patch-2")); + assertThat(event.getPullRequest().getHead().getLabel(), is("skalnik:patch-2")); + assertThat(event.getPullRequest().getHead().getSha(), is("b7a1f9c27caa4e03c14a88feb56e2d4f7500aa63")); + assertThat(event.getPullRequest().getBase().getUser().getLogin(), is("baxterthehacker")); + assertThat(event.getPullRequest().getBase().getRef(), is("master")); + assertThat(event.getPullRequest().getBase().getLabel(), is("baxterthehacker:master")); + assertThat(event.getPullRequest().getBase().getSha(), is("9049f1265b7d61be4a8904a9a27120d2064dab3b")); + + assertThat(event.getRepository().getName(), is("public-repo")); + assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); + + assertThat(event.getSender().getLogin(), is("baxterthehacker")); + } -// TODO implement support classes and write test -// @Test -// public void pull_request_review_comment() throws Exception {} + @Test + public void pull_request_review_comment() throws Exception { + GHEventPayload.PullRequestReviewComment event = + GitHub.offline().parseEventPayload(payload.asReader(), GHEventPayload.PullRequestReviewComment.class); + assertThat(event.getAction(), is("created")); + + assertThat(event.getComment().getBody(), is("Maybe you should use more emojji on this line.")); + + assertThat(event.getPullRequest().getNumber(), is(1)); + assertThat(event.getPullRequest().getTitle(), is("Update the README with new information")); + assertThat(event.getPullRequest().getBody(), is("This is a pretty simple change that we need to pull into master.")); + assertThat(event.getPullRequest().getUser().getLogin(), is("baxterthehacker")); + assertThat(event.getPullRequest().getHead().getUser().getLogin(), is("baxterthehacker")); + assertThat(event.getPullRequest().getHead().getRef(), is("changes")); + assertThat(event.getPullRequest().getHead().getLabel(), is("baxterthehacker:changes")); + assertThat(event.getPullRequest().getHead().getSha(), is("0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c")); + assertThat(event.getPullRequest().getBase().getUser().getLogin(), is("baxterthehacker")); + assertThat(event.getPullRequest().getBase().getRef(), is("master")); + assertThat(event.getPullRequest().getBase().getLabel(), is("baxterthehacker:master")); + assertThat(event.getPullRequest().getBase().getSha(), is("9049f1265b7d61be4a8904a9a27120d2064dab3b")); + + assertThat(event.getRepository().getName(), is("public-repo")); + assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); + + assertThat(event.getSender().getLogin(), is("baxterthehacker")); + } @Test public void push() throws Exception { From 7735edeae87652c1fa8196e7956851a39f5a84d4 Mon Sep 17 00:00:00 2001 From: Arne Burmeister Date: Mon, 23 Oct 2017 17:05:02 +0200 Subject: [PATCH 301/390] extend id from int to long --- .../org/kohsuke/github/GHDeploymentStatusBuilder.java | 4 ++-- src/main/java/org/kohsuke/github/GHObject.java | 8 ++++---- src/main/java/org/kohsuke/github/GHRepository.java | 4 ++-- src/main/java/org/kohsuke/github/GitHub.java | 2 +- src/test/java/org/kohsuke/github/AppTest.java | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java b/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java index f028b6f889..badd33f9f7 100644 --- a/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java +++ b/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java @@ -5,9 +5,9 @@ public class GHDeploymentStatusBuilder { private final Requester builder; private GHRepository repo; - private int deploymentId; + private long deploymentId; - public GHDeploymentStatusBuilder(GHRepository repo, int deploymentId, GHDeploymentState state) { + public GHDeploymentStatusBuilder(GHRepository repo, long deploymentId, GHDeploymentState state) { this.repo = repo; this.deploymentId = deploymentId; this.builder = new Requester(repo.root); diff --git a/src/main/java/org/kohsuke/github/GHObject.java b/src/main/java/org/kohsuke/github/GHObject.java index 96e41a2559..4a4faf8deb 100644 --- a/src/main/java/org/kohsuke/github/GHObject.java +++ b/src/main/java/org/kohsuke/github/GHObject.java @@ -25,7 +25,7 @@ public abstract class GHObject { protected Map> responseHeaderFields; protected String url; - protected int id; + protected long id; protected String created_at; protected String updated_at; @@ -84,13 +84,13 @@ public Date getUpdatedAt() throws IOException { /** * Unique ID number of this resource. */ - @WithBridgeMethods(value=String.class, adapterMethod="intToString") - public int getId() { + @WithBridgeMethods(value=String.class, adapterMethod="longToString") + public long getId() { return id; } @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD", justification = "Bridge method of getId") - private Object intToString(int id, Class type) { + private Object longToString(long id, Class type) { return String.valueOf(id); } diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 29cac80d44..a743e16ed2 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -95,7 +95,7 @@ public GHDeploymentBuilder createDeployment(String ref) { return new GHDeploymentBuilder(this,ref); } - public PagedIterable getDeploymentStatuses(final int id) { + public PagedIterable getDeploymentStatuses(final long id) { return new PagedIterable() { public PagedIterator _iterator(int pageSize) { return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("deployments")+"/"+id+"/statuses", GHDeploymentStatus[].class, pageSize)) { @@ -140,7 +140,7 @@ private String getParam(String name, String value) { return StringUtils.trimToNull(value)== null? null: name+"="+value; } - public GHDeploymentStatusBuilder createDeployStatus(int deploymentId, GHDeploymentState ghDeploymentState) { + public GHDeploymentStatusBuilder createDeployStatus(long deploymentId, GHDeploymentState ghDeploymentState) { return new GHDeploymentStatusBuilder(this,deploymentId,ghDeploymentState); } diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 62c1b4e80c..5c9ad4715f 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -793,7 +793,7 @@ public PagedIterable listAllPublicRepositories() { * This provides a dump of every public repository, in the order that they were created. * * @param since - * The integer ID of the last Repository that you’ve seen. See {@link GHRepository#getId()} + * The numeric ID of the last Repository that you’ve seen. See {@link GHRepository#getId()} * @see documentation */ public PagedIterable listAllPublicRepositories(final String since) { diff --git a/src/test/java/org/kohsuke/github/AppTest.java b/src/test/java/org/kohsuke/github/AppTest.java index 7087920dd7..5d1d96db0c 100755 --- a/src/test/java/org/kohsuke/github/AppTest.java +++ b/src/test/java/org/kohsuke/github/AppTest.java @@ -784,7 +784,7 @@ public void testListAllRepositories() throws Exception { GHRepository r = itr.next(); System.out.println(r.getFullName()); assertNotNull(r.getUrl()); - assertNotEquals(0,r.getId()); + assertNotEquals(0L,r.getId()); } } From 6415785220b2cfab393a12a68efcc4c274d208a2 Mon Sep 17 00:00:00 2001 From: Arne Burmeister Date: Mon, 23 Oct 2017 17:05:31 +0200 Subject: [PATCH 302/390] boyscout: updated dependencies --- pom.xml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index ff898cccd0..3299352264 100644 --- a/pom.xml +++ b/pom.xml @@ -64,7 +64,7 @@ com.infradna.tool bridge-method-injector - 1.14 + 1.17 @@ -108,7 +108,7 @@ junit junit - 4.11 + 4.12 test @@ -120,7 +120,7 @@ com.fasterxml.jackson.core jackson-databind - 2.2.3 + 2.9.2 commons-io @@ -130,7 +130,7 @@ com.infradna.tool bridge-method-annotation - 1.14 + 1.17 org.kohsuke.stapler @@ -141,7 +141,7 @@ org.eclipse.jgit org.eclipse.jgit - 3.1.0.201310021548-r + 4.9.0.201710071750-r test @@ -153,25 +153,25 @@ com.squareup.okhttp3 okhttp-urlconnection - 3.4.0 + 3.9.0 true org.kohsuke wordnet-random-name - 1.2 + 1.3 test org.mockito mockito-all - 1.9.5 + 1.10.19 test com.google.code.findbugs annotations - 3.0.0 + 3.0.1 provided From 40d8f4a352d57dbb214759d32c6f38ffbeb2914d Mon Sep 17 00:00:00 2001 From: iraleigh Date: Tue, 24 Oct 2017 14:24:25 -0700 Subject: [PATCH 303/390] Fixed OAuth connection to enterprise API --- 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 62c1b4e80c..7eabda9a54 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -178,6 +178,10 @@ public static GitHub connectToEnterprise(String apiUrl, String oauthAccessToken) return new GitHubBuilder().withEndpoint(apiUrl).withOAuthToken(oauthAccessToken).build(); } + public static GitHub connectToEnterpriseWtihOAuth(String apiUrl, String login, String oauthAccessToken) throws IOException { + return new GitHubBuilder().withEndpoint(apiUrl).withOAuthToken(oauthAccessToken, login).build(); + } + public static GitHub connectToEnterprise(String apiUrl, String login, String password) throws IOException { return new GitHubBuilder().withEndpoint(apiUrl).withPassword(login, password).build(); } From 46dce17abc958dcb70b5a655d6931c13f6ecf9a9 Mon Sep 17 00:00:00 2001 From: iraleigh Date: Tue, 24 Oct 2017 14:53:23 -0700 Subject: [PATCH 304/390] Fixed Typo --- 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 7eabda9a54..c486445ce1 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -178,7 +178,7 @@ public static GitHub connectToEnterprise(String apiUrl, String oauthAccessToken) return new GitHubBuilder().withEndpoint(apiUrl).withOAuthToken(oauthAccessToken).build(); } - public static GitHub connectToEnterpriseWtihOAuth(String apiUrl, String login, String oauthAccessToken) throws IOException { + public static GitHub connectToEnterpriseWithOAuth(String apiUrl, String login, String oauthAccessToken) throws IOException { return new GitHubBuilder().withEndpoint(apiUrl).withOAuthToken(oauthAccessToken, login).build(); } From 569fa06d2dd51877b3df7b7807c60ae18e167198 Mon Sep 17 00:00:00 2001 From: Baptiste Mathus Date: Wed, 25 Oct 2017 14:06:28 +0200 Subject: [PATCH 305/390] Labels: add method to update color --- src/main/java/org/kohsuke/github/GHLabel.java | 4 ++++ src/test/java/org/kohsuke/github/AppTest.java | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHLabel.java b/src/main/java/org/kohsuke/github/GHLabel.java index 5d1b3b48a2..83a6964a97 100644 --- a/src/main/java/org/kohsuke/github/GHLabel.java +++ b/src/main/java/org/kohsuke/github/GHLabel.java @@ -34,4 +34,8 @@ public String getColor() { public void delete() throws IOException { repo.root.retrieve().method("DELETE").to(url); } + + public void updateColor(String newColor) throws IOException { + repo.root.retrieve().method("PATCH").with("name", name).with("color", newColor).to(url); + } } diff --git a/src/test/java/org/kohsuke/github/AppTest.java b/src/test/java/org/kohsuke/github/AppTest.java index 7087920dd7..6c7a84bbc3 100755 --- a/src/test/java/org/kohsuke/github/AppTest.java +++ b/src/test/java/org/kohsuke/github/AppTest.java @@ -753,6 +753,10 @@ public void testRepoLabel() throws IOException { assertEquals(t.getColor(), "123456"); assertEquals(t.getColor(), t2.getColor()); assertEquals(t.getUrl(), t2.getUrl()); + + t.updateColor("000000"); + GHLabel t3 = r.getLabel("test"); + assertEquals(t3.getColor(), "000000"); t.delete(); } } From e94ba74058fa806af30095b1a4c38c0196c6569c Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 28 Oct 2017 07:44:23 -0700 Subject: [PATCH 306/390] Convention is to call these methods setXyz. Plus doc --- src/main/java/org/kohsuke/github/GHLabel.java | 6 +++++- src/test/java/org/kohsuke/github/AppTest.java | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHLabel.java b/src/main/java/org/kohsuke/github/GHLabel.java index 83a6964a97..3792fdcca3 100644 --- a/src/main/java/org/kohsuke/github/GHLabel.java +++ b/src/main/java/org/kohsuke/github/GHLabel.java @@ -35,7 +35,11 @@ public void delete() throws IOException { repo.root.retrieve().method("DELETE").to(url); } - public void updateColor(String newColor) throws IOException { + /** + * @param newColor + * 6-letter hex color code, like "f29513" + */ + public void setColor(String newColor) throws IOException { repo.root.retrieve().method("PATCH").with("name", name).with("color", newColor).to(url); } } diff --git a/src/test/java/org/kohsuke/github/AppTest.java b/src/test/java/org/kohsuke/github/AppTest.java index 6c7a84bbc3..f3041044b8 100755 --- a/src/test/java/org/kohsuke/github/AppTest.java +++ b/src/test/java/org/kohsuke/github/AppTest.java @@ -754,7 +754,7 @@ public void testRepoLabel() throws IOException { assertEquals(t.getColor(), t2.getColor()); assertEquals(t.getUrl(), t2.getUrl()); - t.updateColor("000000"); + t.setColor("000000"); GHLabel t3 = r.getLabel("test"); assertEquals(t3.getColor(), "000000"); t.delete(); From 4849619d679d3f94d1637aa99229714372e33a72 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 28 Oct 2017 07:54:41 -0700 Subject: [PATCH 307/390] None of the connectToEnterprise methods are preferrable so document accordingly --- src/main/java/org/kohsuke/github/GitHub.java | 20 +++++++++++++++---- .../org/kohsuke/github/GitHubBuilder.java | 6 ++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index c486445ce1..60fe15e493 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -166,6 +166,16 @@ public static GitHub connect() throws IOException { return GitHubBuilder.fromCredentials().build(); } + /** + * Version that connects to GitHub Enterprise. + * + * @deprecated + * Use {@link #connectToEnterpriseWithOAuth(String, String, String)} + */ + public static GitHub connectToEnterprise(String apiUrl, String oauthAccessToken) throws IOException { + return connectToEnterpriseWithOAuth(apiUrl,null,oauthAccessToken); + } + /** * Version that connects to GitHub Enterprise. * @@ -174,14 +184,16 @@ public static GitHub connect() throws IOException { * "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. */ - public static GitHub connectToEnterprise(String apiUrl, String oauthAccessToken) throws IOException { - return new GitHubBuilder().withEndpoint(apiUrl).withOAuthToken(oauthAccessToken).build(); - } - public static GitHub connectToEnterpriseWithOAuth(String apiUrl, String login, String oauthAccessToken) throws IOException { return new GitHubBuilder().withEndpoint(apiUrl).withOAuthToken(oauthAccessToken, login).build(); } + /** + * Version that connects to GitHub Enterprise. + * + * @deprecated + * Use with caution. Login with password is not a preferred method. + */ public static GitHub connectToEnterprise(String apiUrl, String login, String password) throws IOException { return new GitHubBuilder().withEndpoint(apiUrl).withPassword(login, password).build(); } diff --git a/src/main/java/org/kohsuke/github/GitHubBuilder.java b/src/main/java/org/kohsuke/github/GitHubBuilder.java index 62a99a6272..e54359892c 100644 --- a/src/main/java/org/kohsuke/github/GitHubBuilder.java +++ b/src/main/java/org/kohsuke/github/GitHubBuilder.java @@ -154,6 +154,12 @@ public static GitHubBuilder fromProperties(Properties props) { return self; } + /** + * @param endpoint + * 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. + */ public GitHubBuilder withEndpoint(String endpoint) { this.endpoint = endpoint; return this; From b6063dd534df6b4c598de25d0177b001874591d0 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 28 Oct 2017 08:42:27 -0700 Subject: [PATCH 308/390] Restored binary compatibility --- .../github/GHDeploymentStatusBuilder.java | 8 ++++++++ src/main/java/org/kohsuke/github/GHObject.java | 9 ++++++--- .../java/org/kohsuke/github/GHRepository.java | 16 ++++++++++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java b/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java index badd33f9f7..13d08071e2 100644 --- a/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java +++ b/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java @@ -7,6 +7,14 @@ public class GHDeploymentStatusBuilder { private GHRepository repo; private long deploymentId; + /** + * @deprecated + * ID is long now. + */ + public GHDeploymentStatusBuilder(GHRepository repo, int deploymentId, GHDeploymentState state) { + this(repo,(long)deploymentId,state); + } + public GHDeploymentStatusBuilder(GHRepository repo, long deploymentId, GHDeploymentState state) { this.repo = repo; this.deploymentId = deploymentId; diff --git a/src/main/java/org/kohsuke/github/GHObject.java b/src/main/java/org/kohsuke/github/GHObject.java index 4a4faf8deb..45ca69750e 100644 --- a/src/main/java/org/kohsuke/github/GHObject.java +++ b/src/main/java/org/kohsuke/github/GHObject.java @@ -84,14 +84,17 @@ public Date getUpdatedAt() throws IOException { /** * Unique ID number of this resource. */ - @WithBridgeMethods(value=String.class, adapterMethod="longToString") + @WithBridgeMethods(value={String.class,int.class}, adapterMethod="longToStringOrInt") public long getId() { return id; } @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD", justification = "Bridge method of getId") - private Object longToString(long id, Class type) { - return String.valueOf(id); + private Object longToStringOrInt(long id, Class type) { + if (type==String.class) + return String.valueOf(id); + else + return (int)id; } @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD", justification = "Bridge method of getHtmlUrl") diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index a743e16ed2..1ae163d152 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -95,6 +95,14 @@ public GHDeploymentBuilder createDeployment(String ref) { return new GHDeploymentBuilder(this,ref); } + /** + * @deprecated + * Use {@link #getDeploymentStatuses(long)} + */ + public PagedIterable getDeploymentStatuses(final int id) { + return getDeploymentStatuses((long)id); + } + public PagedIterable getDeploymentStatuses(final long id) { return new PagedIterable() { public PagedIterator _iterator(int pageSize) { @@ -140,6 +148,14 @@ private String getParam(String name, String value) { return StringUtils.trimToNull(value)== null? null: name+"="+value; } + /** + * @deprecated + * Use {@link #createDeployStatus(long, GHDeploymentState)} + */ + public GHDeploymentStatusBuilder createDeployStatus(int deploymentId, GHDeploymentState ghDeploymentState) { + return createDeployStatus((long)deploymentId,ghDeploymentState); + } + public GHDeploymentStatusBuilder createDeployStatus(long deploymentId, GHDeploymentState ghDeploymentState) { return new GHDeploymentStatusBuilder(this,deploymentId,ghDeploymentState); } From ab3d9e82efc34b45f53dd94bf7e08046bd801612 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 28 Oct 2017 08:43:48 -0700 Subject: [PATCH 309/390] A little better version of the bridge method --- src/main/java/org/kohsuke/github/GHObject.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHObject.java b/src/main/java/org/kohsuke/github/GHObject.java index 45ca69750e..3b26ed77cc 100644 --- a/src/main/java/org/kohsuke/github/GHObject.java +++ b/src/main/java/org/kohsuke/github/GHObject.java @@ -93,8 +93,9 @@ public long getId() { private Object longToStringOrInt(long id, Class type) { if (type==String.class) return String.valueOf(id); - else + if (type==int.class) return (int)id; + throw new AssertionError("Unexpected type: "+type); } @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD", justification = "Bridge method of getHtmlUrl") From 83c2c4e92e7026a68b77d37f2524e9b1c44ef2dc Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 28 Oct 2017 08:59:41 -0700 Subject: [PATCH 310/390] Fixed the broken design of how GHDeploymentStatus get exposed. --- .../java/org/kohsuke/github/GHDeployment.java | 26 ++++++++++++++ .../github/GHDeploymentStatusBuilder.java | 12 +++++-- .../java/org/kohsuke/github/GHRepository.java | 36 +++++++------------ 3 files changed, 47 insertions(+), 27 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHDeployment.java b/src/main/java/org/kohsuke/github/GHDeployment.java index 0cef10ee52..42118f3329 100644 --- a/src/main/java/org/kohsuke/github/GHDeployment.java +++ b/src/main/java/org/kohsuke/github/GHDeployment.java @@ -3,6 +3,13 @@ import java.io.IOException; import java.net.URL; +/** + * Represents a deployment + * + * @see documentation + * @see GHRepository#listDeployments(String, String, String, String) + * @see GHRepository#getDeployment(long) + */ public class GHDeployment extends GHObject { private GHRepository owner; private GitHub root; @@ -58,4 +65,23 @@ public String getSha(){ public URL getHtmlUrl() { return null; } + + public GHDeploymentStatusBuilder createStatus(GHDeploymentState state) { + return new GHDeploymentStatusBuilder(owner,id,state); + } + + public PagedIterable listStatuses() { + return new PagedIterable() { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator(statuses_url, GHDeploymentStatus[].class, pageSize)) { + @Override + protected void wrapUp(GHDeploymentStatus[] page) { + for (GHDeploymentStatus c : page) + c.wrap(owner); + } + }; + } + }; + } + } diff --git a/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java b/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java index 13d08071e2..821a3e744e 100644 --- a/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java +++ b/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java @@ -2,6 +2,12 @@ import java.io.IOException; +/** + * Creates a new deployment status. + * + * @see + * GHDeployment#createStatus(GHDeploymentState) + */ public class GHDeploymentStatusBuilder { private final Requester builder; private GHRepository repo; @@ -9,13 +15,13 @@ public class GHDeploymentStatusBuilder { /** * @deprecated - * ID is long now. + * Use {@link GHDeployment#createStatus(GHDeploymentState)} */ public GHDeploymentStatusBuilder(GHRepository repo, int deploymentId, GHDeploymentState state) { this(repo,(long)deploymentId,state); } - public GHDeploymentStatusBuilder(GHRepository repo, long deploymentId, GHDeploymentState state) { + /*package*/ GHDeploymentStatusBuilder(GHRepository repo, long deploymentId, GHDeploymentState state) { this.repo = repo; this.deploymentId = deploymentId; this.builder = new Requester(repo.root); @@ -33,6 +39,6 @@ public GHDeploymentStatusBuilder targetUrl(String targetUrl) { } public GHDeploymentStatus create() throws IOException { - return builder.to(repo.getApiTailUrl("deployments")+"/"+deploymentId+"/statuses",GHDeploymentStatus.class).wrap(repo); + return builder.to(repo.getApiTailUrl("deployments/"+deploymentId+"/statuses"),GHDeploymentStatus.class).wrap(repo); } } diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 1ae163d152..4dfd1397bc 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -97,24 +97,10 @@ public GHDeploymentBuilder createDeployment(String ref) { /** * @deprecated - * Use {@link #getDeploymentStatuses(long)} + * Use {@code getDeployment(id).listStatuses()} */ - public PagedIterable getDeploymentStatuses(final int id) { - return getDeploymentStatuses((long)id); - } - - public PagedIterable getDeploymentStatuses(final long id) { - return new PagedIterable() { - public PagedIterator _iterator(int pageSize) { - return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("deployments")+"/"+id+"/statuses", GHDeploymentStatus[].class, pageSize)) { - @Override - protected void wrapUp(GHDeploymentStatus[] page) { - for (GHDeploymentStatus c : page) - c.wrap(GHRepository.this); - } - }; - } - }; + public PagedIterable getDeploymentStatuses(final int id) throws IOException { + return getDeployment(id).listStatuses(); } public PagedIterable listDeployments(String sha,String ref,String task,String environment){ @@ -131,7 +117,13 @@ protected void wrapUp(GHDeployment[] page) { }; } }; + } + /** + * Obtains a single {@link GHDeployment} by its ID. + */ + public GHDeployment getDeployment(long id) throws IOException { + return root.retrieve().to("deployments/" + id, GHDeployment.class).wrap(this); } private String join(List params, String joinStr) { @@ -150,14 +142,10 @@ private String getParam(String name, String value) { /** * @deprecated - * Use {@link #createDeployStatus(long, GHDeploymentState)} + * Use {@code getDeployment(deploymentId).createStatus(ghDeploymentState)} */ - public GHDeploymentStatusBuilder createDeployStatus(int deploymentId, GHDeploymentState ghDeploymentState) { - return createDeployStatus((long)deploymentId,ghDeploymentState); - } - - public GHDeploymentStatusBuilder createDeployStatus(long deploymentId, GHDeploymentState ghDeploymentState) { - return new GHDeploymentStatusBuilder(this,deploymentId,ghDeploymentState); + public GHDeploymentStatusBuilder createDeployStatus(int deploymentId, GHDeploymentState ghDeploymentState) throws IOException { + return getDeployment(deploymentId).createStatus(ghDeploymentState); } private static class GHRepoPermission { From 60c9ba88ae3e2df490ba1426c3d474aa47a5de73 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 28 Oct 2017 15:27:38 -0700 Subject: [PATCH 311/390] Updated tests --- src/test/java/org/kohsuke/github/AppTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/kohsuke/github/AppTest.java b/src/test/java/org/kohsuke/github/AppTest.java index 9c75684356..e069a74edb 100755 --- a/src/test/java/org/kohsuke/github/AppTest.java +++ b/src/test/java/org/kohsuke/github/AppTest.java @@ -134,10 +134,10 @@ public void testGetDeploymentStatuses() throws IOException { .description("question") .payload("{\"user\":\"atmos\",\"room_id\":123456}") .create(); - GHDeploymentStatus ghDeploymentStatus = repository.createDeployStatus(deployment.getId(), GHDeploymentState.SUCCESS) + GHDeploymentStatus ghDeploymentStatus = deployment.createStatus(GHDeploymentState.SUCCESS) .description("success") .targetUrl("http://www.github.com").create(); - Iterable deploymentStatuses = repository.getDeploymentStatuses(deployment.getId()); + Iterable deploymentStatuses = deployment.listStatuses(); assertNotNull(deploymentStatuses); assertEquals(1,Iterables.size(deploymentStatuses)); assertEquals(ghDeploymentStatus.getId(), Iterables.get(deploymentStatuses, 0).getId()); From 0b069df9cefcfc9c17a55c2fea59d8929b0e46f6 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 28 Oct 2017 15:48:26 -0700 Subject: [PATCH 312/390] Pick up the version that fixes int->long adaption --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3299352264..21816ef4a7 100644 --- a/pom.xml +++ b/pom.xml @@ -64,7 +64,7 @@ com.infradna.tool bridge-method-injector - 1.17 + 1.18 From 2b7c5249085c21d46163d1ec85da107ce6b914a3 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 28 Oct 2017 15:54:33 -0700 Subject: [PATCH 313/390] [maven-release-plugin] prepare release github-api-1.90 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 21816ef4a7..bc4e873120 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.90-SNAPSHOT + 1.90 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - HEAD + github-api-1.90 From e25ae27a153e7462bd6fa56bd4da9da0918f5a5c Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 28 Oct 2017 15:54:44 -0700 Subject: [PATCH 314/390] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index bc4e873120..dfdc0e7289 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.90 + 1.91-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - github-api-1.90 + HEAD From ab24e6e1c12b9ecbdbe83fad8fbbe22a43780b2f Mon Sep 17 00:00:00 2001 From: sg012265 Date: Mon, 30 Oct 2017 15:32:25 -0500 Subject: [PATCH 315/390] Add get for all orgs --- src/main/java/org/kohsuke/github/GitHub.java | 32 +++++++++++++++++++ .../java/org/kohsuke/github/GitHubTest.java | 17 ++++++++-- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 67fc1f8fe4..1013508c01 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -424,6 +424,9 @@ protected GHUser getUser(GHUser orig) { return u; } + /** + * Gets {@link GHOrganization} specified by name. + */ public GHOrganization getOrganization(String name) throws IOException { GHOrganization o = orgs.get(name); if (o==null) { @@ -433,6 +436,35 @@ public GHOrganization getOrganization(String name) throws IOException { return o; } + /** + * Gets a list of all organizations. + */ + public PagedIterable getOrganizations() { + return getOrganizations(null); + } + + /** + * Gets a list of all organizations starting after the organization identifier specified by 'since'. + * + * @see List All Orgs - Parameters + */ + public PagedIterable getOrganizations(final String since) { + return new PagedIterable() { + @Override + public PagedIterator _iterator(int pageSize) { + System.out.println("page size: " + pageSize); + return new PagedIterator(retrieve().with("since",since) + .asIterator("/organizations", GHOrganization[].class, pageSize)) { + @Override + protected void wrapUp(GHOrganization[] page) { + for (GHOrganization c : page) + c.wrapUp(GitHub.this); + } + }; + } + }; + } + /** * Gets the repository object from 'user/reponame' string that GitHub calls as "repository name" * diff --git a/src/test/java/org/kohsuke/github/GitHubTest.java b/src/test/java/org/kohsuke/github/GitHubTest.java index a418db5fde..9b30d31b6e 100644 --- a/src/test/java/org/kohsuke/github/GitHubTest.java +++ b/src/test/java/org/kohsuke/github/GitHubTest.java @@ -3,13 +3,12 @@ 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.*; import com.google.common.collect.Iterables; import org.junit.Test; +import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; @@ -155,4 +154,16 @@ public void listUsers() throws IOException { System.out.println(u.getName()); } } + + @Test + public void getOrgs() throws IOException { + GitHub hub = GitHub.connect(); + int iterations = 10; + Set orgIds = new HashSet(); + for (GHOrganization org : Iterables.limit(hub.getOrganizations().withPageSize(2), iterations)) { + orgIds.add(org.getId()); + System.out.println(org.getName()); + } + assertThat(orgIds.size(), equalTo(iterations)); + } } From 35ba2671155953278e7e491466b3a379d6cd087e Mon Sep 17 00:00:00 2001 From: sg012265 Date: Mon, 30 Oct 2017 15:38:19 -0500 Subject: [PATCH 316/390] Revert wildcard usage for imports --- src/test/java/org/kohsuke/github/GitHubTest.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/test/java/org/kohsuke/github/GitHubTest.java b/src/test/java/org/kohsuke/github/GitHubTest.java index 9b30d31b6e..c6e1e4113a 100644 --- a/src/test/java/org/kohsuke/github/GitHubTest.java +++ b/src/test/java/org/kohsuke/github/GitHubTest.java @@ -3,7 +3,11 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.lang.reflect.Field; -import java.util.*; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; import com.google.common.collect.Iterables; import org.junit.Test; From ab6253cbd0a0d82c72ce5e212a799c7d40c36755 Mon Sep 17 00:00:00 2001 From: Rechi Date: Thu, 9 Nov 2017 22:41:49 +0100 Subject: [PATCH 317/390] [fix] GHPerson: check if root is null --- src/main/java/org/kohsuke/github/GHPerson.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHPerson.java b/src/main/java/org/kohsuke/github/GHPerson.java index f9872699ce..87cb8efaa7 100644 --- a/src/main/java/org/kohsuke/github/GHPerson.java +++ b/src/main/java/org/kohsuke/github/GHPerson.java @@ -41,7 +41,7 @@ protected synchronized void populate() throws IOException { if (created_at!=null) { return; // already populated } - if (root.isOffline()) { + if (root == null || root.isOffline()) { return; // cannot populate, will have to live with what we have } root.retrieve().to(url, this); From c80b8f60f820db6ee1af17305308a9db62b55781 Mon Sep 17 00:00:00 2001 From: Michiaki Mizoguchi Date: Thu, 16 Nov 2017 12:36:31 +0900 Subject: [PATCH 318/390] Add GHIssue#setMilestone --- src/main/java/org/kohsuke/github/GHIssue.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHIssue.java b/src/main/java/org/kohsuke/github/GHIssue.java index 117c06f8d8..186ea16719 100644 --- a/src/main/java/org/kohsuke/github/GHIssue.java +++ b/src/main/java/org/kohsuke/github/GHIssue.java @@ -203,6 +203,10 @@ public void setBody(String body) throws IOException { edit("body",body); } + public void setMilestone(GHMilestone milestone) throws IOException { + edit("milestone",milestone.getNumber()); + } + public void assignTo(GHUser user) throws IOException { setAssignees(user); } From 15991fd2f763a40dd21c2a7715735abd87de9423 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lesaint?= Date: Thu, 30 Nov 2017 14:38:47 +0100 Subject: [PATCH 319/390] PullRequest review state and event do not have same values this fixes parsing of response of WS call submitting a review to fail when event of new review is REQUEST_CHANGES also, specifying event when creating a pending PR review is useless and providing it when submitting the review is enough --- .../org/kohsuke/github/GHPullRequest.java | 15 +++---- .../kohsuke/github/GHPullRequestReview.java | 7 ++-- .../github/GHPullRequestReviewEvent.java | 41 +++++++++++++++++++ .../github/GHPullRequestReviewState.java | 20 +++------ .../org/kohsuke/github/PullRequestTest.java | 2 +- 5 files changed, 56 insertions(+), 29 deletions(-) create mode 100644 src/main/java/org/kohsuke/github/GHPullRequestReviewEvent.java diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index 9342623829..99db3bf32c 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -23,7 +23,6 @@ */ package org.kohsuke.github; -import javax.annotation.CheckForNull; import java.io.IOException; import java.net.URL; import java.util.ArrayList; @@ -298,23 +297,19 @@ protected void wrapUp(GHPullRequestCommitDetail[] page) { @Preview @Deprecated - public GHPullRequestReview createReview(String body, @CheckForNull GHPullRequestReviewState event, - GHPullRequestReviewComment... comments) + public GHPullRequestReview createReview(String body, GHPullRequestReviewComment... comments) throws IOException { - return createReview(body, event, Arrays.asList(comments)); + return createReview(body, Arrays.asList(comments)); } @Preview @Deprecated - public GHPullRequestReview createReview(String body, @CheckForNull GHPullRequestReviewState event, - List comments) + public GHPullRequestReview createReview(String body, List comments) throws IOException { -// if (event == null) { -// event = GHPullRequestReviewState.PENDING; -// } List draftComments = new ArrayList(comments.size()); for (GHPullRequestReviewComment c : comments) { - draftComments.add(new DraftReviewComment(c.getBody(), c.getPath(), c.getPosition())); + Integer position = c.getPosition(); + draftComments.add(new DraftReviewComment(c.getBody(), c.getPath(), position == null ? 0 : position /*FIXME do not use GHPullRequestReviewComment for new comments*/)); } return new Requester(root).method("POST") .with("body", body) diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReview.java b/src/main/java/org/kohsuke/github/GHPullRequestReview.java index d7afe59aad..c96e8f1491 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestReview.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestReview.java @@ -25,6 +25,7 @@ import java.io.IOException; import java.net.URL; +import javax.annotation.CheckForNull; import static org.kohsuke.github.Previews.*; @@ -32,7 +33,7 @@ * Review to the pull request * * @see GHPullRequest#listReviews() - * @see GHPullRequest#createReview(String, GHPullRequestReviewState, GHPullRequestReviewComment...) + * @see GHPullRequest#createReview(String, GHPullRequestReviewComment...) */ public class GHPullRequestReview extends GHObject { GHPullRequest owner; @@ -72,6 +73,7 @@ public String getCommitId() { return commit_id; } + @CheckForNull public GHPullRequestReviewState getState() { return state; } @@ -90,14 +92,13 @@ protected String getApiRoute() { */ @Preview @Deprecated - public void submit(String body, GHPullRequestReviewState event) throws IOException { + public void submit(String body, GHPullRequestReviewEvent event) throws IOException { new Requester(owner.root).method("POST") .with("body", body) .with("event", event.action()) .withPreview("application/vnd.github.black-cat-preview+json") .to(getApiRoute()+"/events",this); this.body = body; - this.state = event; } /** diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReviewEvent.java b/src/main/java/org/kohsuke/github/GHPullRequestReviewEvent.java new file mode 100644 index 0000000000..4a5d66094f --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHPullRequestReviewEvent.java @@ -0,0 +1,41 @@ +/* + * The MIT License + * + * Copyright (c) 2011, Eric Maupin + * + * 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; + +public enum GHPullRequestReviewEvent { + PENDING(null), + APPROVE("APPROVE"), + REQUEST_CHANGES("REQUEST_CHANGES"), + COMMENT("COMMENT"); + + private final String _action; + + GHPullRequestReviewEvent(String action) { + _action = action; + } + + public String action() { + return _action; + } +} diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReviewState.java b/src/main/java/org/kohsuke/github/GHPullRequestReviewState.java index fca3fabfb3..eff7fbf60b 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestReviewState.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestReviewState.java @@ -1,19 +1,9 @@ package org.kohsuke.github; public enum GHPullRequestReviewState { - PENDING(null), - APPROVED("APPROVE"), - REQUEST_CHANGES("REQUEST_CHANGES"), - COMMENTED("COMMENT"), - DISMISSED(null); - - private final String _action; - - GHPullRequestReviewState(String action) { - _action = action; - } - - public String action() { - return _action; - } + PENDING, + APPROVED, + CHANGES_REQUESTED, + COMMENTED, + DISMISSED } diff --git a/src/test/java/org/kohsuke/github/PullRequestTest.java b/src/test/java/org/kohsuke/github/PullRequestTest.java index 5ea2628303..bf45e35c46 100644 --- a/src/test/java/org/kohsuke/github/PullRequestTest.java +++ b/src/test/java/org/kohsuke/github/PullRequestTest.java @@ -45,7 +45,7 @@ public void testPullRequestReviews() throws Exception { assertThat(review.getState(), is(GHPullRequestReviewState.PENDING)); assertThat(review.getBody(), is("Some draft review")); assertThat(review.getCommitId(), notNullValue()); - review.submit("Some review comment", GHPullRequestReviewState.COMMENTED); + review.submit("Some review comment", GHPullRequestReviewEvent.COMMENT); List comments = review.listReviewComments().asList(); assertEquals(1, comments.size()); GHPullRequestReviewComment comment = comments.get(0); From fa16261d7a7e96552b5694c0c24120da5afba1a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lesaint?= Date: Thu, 30 Nov 2017 14:39:16 +0100 Subject: [PATCH 320/390] position of pr comment can be null and original_position is not parsed position of pr comment is null when comment is outdated (ie. not located in diff patch anymore) --- .../kohsuke/github/GHPullRequestReviewComment.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java b/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java index 33097bc29d..f1a2c603da 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java @@ -25,6 +25,7 @@ import java.io.IOException; import java.net.URL; +import javax.annotation.CheckForNull; import static org.kohsuke.github.Previews.*; @@ -41,8 +42,8 @@ public class GHPullRequestReviewComment extends GHObject implements Reactable { private String body; private GHUser user; private String path; - private int position; - private int originalPosition; + private int position = -1; + private int original_position = -1; public static GHPullRequestReviewComment draft(String body, String path, int position) { GHPullRequestReviewComment result = new GHPullRequestReviewComment(); @@ -82,12 +83,14 @@ public String getPath() { return path; } - public int getPosition() { - return position; + @CheckForNull + public Integer getPosition() { + return position == -1 ? null : position; } + @CheckForNull public int getOriginalPosition() { - return originalPosition; + return original_position == -1 ? null : original_position; } @Override From 892d30516546be46f7cebd3a0f920db0801b3e29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lesaint?= Date: Mon, 8 Jan 2018 15:29:22 +0100 Subject: [PATCH 321/390] add Requester#with override for long value --- src/main/java/org/kohsuke/github/Requester.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index 00f11f2426..73a8bfb34e 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -134,6 +134,10 @@ public Requester with(String key, int value) { return _with(key, value); } + public Requester with(String key, long value) { + return _with(key, value); + } + public Requester with(String key, Integer value) { if (value!=null) _with(key, value); From 6961c467a64a43584e026b2438e7a254fcc8f481 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lesaint?= Date: Fri, 1 Dec 2017 17:37:27 +0100 Subject: [PATCH 322/390] create review comment reply from GHPullRequest --- .../java/org/kohsuke/github/GHPullRequest.java | 15 +++++++++++++-- .../github/GHPullRequestReviewComment.java | 11 +++++++++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index 99db3bf32c..369dff911b 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -90,7 +90,7 @@ protected String getApiRoute() { public URL getPatchUrl() { return GitHub.parseURL(patch_url); } - + /** * The URL of the patch file. * like https://github.com/jenkinsci/jenkins/pull/100.patch @@ -113,7 +113,7 @@ public GHCommitPointer getBase() { public GHCommitPointer getHead() { return head; } - + @Deprecated public Date getIssueUpdatedAt() throws IOException { return super.getUpdatedAt(); @@ -328,6 +328,17 @@ public GHPullRequestReviewComment createReviewComment(String body, String sha, S .to(getApiRoute() + "/comments", GHPullRequestReviewComment.class).wrapUp(this); } + /** + * Create a reply to the current comment. + */ + public GHPullRequestReviewComment createReviewCommentReply(GHPullRequestReviewComment comment, String body) throws IOException { + return new Requester(owner.root).method("POST") + .with("body", body) + .with("in_reply_to", comment.getId()) + .to(getApiRoute() + "/comments", GHPullRequestReviewComment.class) + .wrapUp(this); + } + /** * Merge this pull request. * diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java b/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java index f1a2c603da..5ab8861f8d 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java @@ -44,6 +44,8 @@ public class GHPullRequestReviewComment extends GHObject implements Reactable { private String path; private int position = -1; private int original_position = -1; + private long in_reply_to_id = -1L; + public static GHPullRequestReviewComment draft(String body, String path, int position) { GHPullRequestReviewComment result = new GHPullRequestReviewComment(); @@ -89,10 +91,15 @@ public Integer getPosition() { } @CheckForNull - public int getOriginalPosition() { + public Integer getOriginalPosition() { return original_position == -1 ? null : original_position; } + @CheckForNull + public Long getInReplyToId() { + return in_reply_to_id == -1 ? null : in_reply_to_id; + } + @Override public URL getHtmlUrl() { return null; @@ -129,7 +136,7 @@ public GHReaction createReaction(ReactionContent content) throws IOException { public PagedIterable listReactions() { return new PagedIterable() { public PagedIterator _iterator(int pageSize) { - return new PagedIterator(owner.root.retrieve().withPreview(SQUIRREL_GIRL).asIterator(getApiRoute()+"/reactions", GHReaction[].class, pageSize)) { + return new PagedIterator(owner.root.retrieve().withPreview(SQUIRREL_GIRL).asIterator(getApiRoute() + "/reactions", GHReaction[].class, pageSize)) { @Override protected void wrapUp(GHReaction[] page) { for (GHReaction c : page) From e74346fed6d5206d8ab54e4dab5542df597ddd87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lesaint?= Date: Mon, 4 Dec 2017 11:11:58 +0100 Subject: [PATCH 323/390] support create PR review in single API call & remove @Preview --- .../org/kohsuke/github/GHPullRequest.java | 72 ++++++++---- .../kohsuke/github/GHPullRequestReview.java | 109 ++---------------- .../github/GHPullRequestReviewAbstract.java | 101 ++++++++++++++++ .../github/GHPullRequestReviewDraft.java | 53 +++++++++ .../org/kohsuke/github/PullRequestTest.java | 8 +- 5 files changed, 214 insertions(+), 129 deletions(-) create mode 100644 src/main/java/org/kohsuke/github/GHPullRequestReviewAbstract.java create mode 100644 src/main/java/org/kohsuke/github/GHPullRequestReviewDraft.java diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index 369dff911b..5a62936f8d 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -23,6 +23,7 @@ */ package org.kohsuke.github; +import javax.annotation.Nullable; import java.io.IOException; import java.net.URL; import java.util.ArrayList; @@ -35,13 +36,16 @@ /** * A pull request. - * + * * @author Kohsuke Kawaguchi * @see GHRepository#getPullRequest(int) */ @SuppressWarnings({"UnusedDeclaration"}) public class GHPullRequest extends GHIssue { + private static final String COMMENTS_ACTION = "/comments"; + private static final String COMMIT_ID_FIELD = "commit_id"; + private String patch_url, diff_url, issue_url; private GHCommitPointer base; private String merged_at; @@ -245,7 +249,6 @@ public PagedIterable listReviews() { return new PagedIterable() { public PagedIterator _iterator(int pageSize) { return new PagedIterator(root.retrieve() - .withPreview(BLACK_CAT) .asIterator(String.format("%s/reviews", getApiRoute()), GHPullRequestReview[].class, pageSize)) { @Override @@ -265,7 +268,7 @@ protected void wrapUp(GHPullRequestReview[] page) { public PagedIterable listReviewComments() throws IOException { return new PagedIterable() { public PagedIterator _iterator(int pageSize) { - return new PagedIterator(root.retrieve().asIterator(getApiRoute() + "/comments", + return new PagedIterator(root.retrieve().asIterator(getApiRoute() + COMMENTS_ACTION, GHPullRequestReviewComment[].class, pageSize)) { protected void wrapUp(GHPullRequestReviewComment[] page) { for (GHPullRequestReviewComment c : page) @@ -295,37 +298,58 @@ protected void wrapUp(GHPullRequestCommitDetail[] page) { }; } - @Preview - @Deprecated - public GHPullRequestReview createReview(String body, GHPullRequestReviewComment... comments) + public GHPullRequestReview createReview(@Nullable String commitId, String body, GHPullRequestReviewEvent event, + GHPullRequestReviewComment... comments) throws IOException { + return createReview(commitId, body, event, Arrays.asList(comments)); + } + + public GHPullRequestReview createReview(@Nullable String commitId, String body, GHPullRequestReviewEvent event, + List comments) throws IOException { + List draftComments = toDraftReviewComments(comments); + return new Requester(root).method("POST") + .with(COMMIT_ID_FIELD, commitId) + .with("body", body) + .with("event", event.action()) + ._with("comments", draftComments) + .to(getApiRoute() + "/reviews", GHPullRequestReview.class) + .wrapUp(this); + } + + public GHPullRequestReviewDraft newDraftReview(@Nullable String commitId, String body, GHPullRequestReviewComment... comments) throws IOException { - return createReview(body, Arrays.asList(comments)); + return newDraftReview(commitId, body, Arrays.asList(comments)); } - @Preview - @Deprecated - public GHPullRequestReview createReview(String body, List comments) + public GHPullRequestReviewDraft newDraftReview(@Nullable String commitId, String body, List comments) throws IOException { + List draftComments = toDraftReviewComments(comments); + return new Requester(root).method("POST") + .with(COMMIT_ID_FIELD, commitId) + .with("body", body) + ._with("comments", draftComments) + .to(getApiRoute() + "/reviews", GHPullRequestReviewDraft.class) + .wrapUp(this); + } + + private static List toDraftReviewComments(List comments) { List draftComments = new ArrayList(comments.size()); for (GHPullRequestReviewComment c : comments) { Integer position = c.getPosition(); - draftComments.add(new DraftReviewComment(c.getBody(), c.getPath(), position == null ? 0 : position /*FIXME do not use GHPullRequestReviewComment for new comments*/)); + if (position == null) { + throw new IllegalArgumentException("GHPullRequestReviewComment must have a position"); + } + draftComments.add(new DraftReviewComment(c.getBody(), c.getPath(), position)); } - return new Requester(root).method("POST") - .with("body", body) - //.with("event", event.name()) - ._with("comments", draftComments) - .withPreview(BLACK_CAT) - .to(getApiRoute() + "/reviews", GHPullRequestReview.class).wrapUp(this); + return draftComments; } 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(COMMIT_ID_FIELD, sha) .with("path", path) .with("position", position) - .to(getApiRoute() + "/comments", GHPullRequestReviewComment.class).wrapUp(this); + .to(getApiRoute() + COMMENTS_ACTION, GHPullRequestReviewComment.class).wrapUp(this); } /** @@ -335,7 +359,7 @@ public GHPullRequestReviewComment createReviewCommentReply(GHPullRequestReviewCo return new Requester(owner.root).method("POST") .with("body", body) .with("in_reply_to", comment.getId()) - .to(getApiRoute() + "/comments", GHPullRequestReviewComment.class) + .to(getApiRoute() + COMMENTS_ACTION, GHPullRequestReviewComment.class) .wrapUp(this); } @@ -377,10 +401,10 @@ public void merge(String msg, String sha) throws IOException { */ public void merge(String msg, String sha, MergeMethod method) throws IOException { new Requester(root).method("PUT") - .with("commit_message",msg) - .with("sha",sha) - .with("merge_method",method) - .to(getApiRoute()+"/merge"); + .with("commit_message", msg) + .with("sha", sha) + .with("merge_method", method) + .to(getApiRoute() + "/merge"); } public enum MergeMethod{ MERGE, SQUASH, REBASE } diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReview.java b/src/main/java/org/kohsuke/github/GHPullRequestReview.java index c96e8f1491..3bb155b881 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestReview.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestReview.java @@ -24,127 +24,34 @@ package org.kohsuke.github; import java.io.IOException; -import java.net.URL; -import javax.annotation.CheckForNull; - -import static org.kohsuke.github.Previews.*; +import java.util.List; /** * Review to the pull request * * @see GHPullRequest#listReviews() - * @see GHPullRequest#createReview(String, GHPullRequestReviewComment...) + * @see GHPullRequest#createReview(String, String, GHPullRequestReviewEvent, List) */ -public class GHPullRequestReview extends GHObject { - GHPullRequest owner; - - private String body; - private GHUser user; - private String commit_id; +public class GHPullRequestReview extends GHPullRequestReviewAbstract { private GHPullRequestReviewState state; - /*package*/ GHPullRequestReview wrapUp(GHPullRequest owner) { - this.owner = owner; - return this; - } - - /** - * Gets the pull request to which this review is associated. - */ - public GHPullRequest getParent() { - return owner; - } - - /** - * The comment itself. - */ - public String getBody() { - return body; - } - - /** - * Gets the user who posted this review. - */ - public GHUser getUser() throws IOException { - return owner.root.getUser(user.getLogin()); - } - - public String getCommitId() { - return commit_id; - } - - @CheckForNull + @Override public GHPullRequestReviewState getState() { return state; } - @Override - public URL getHtmlUrl() { - return null; - } - - protected String getApiRoute() { - return owner.getApiRoute()+"/reviews/"+id; - } - - /** - * Updates the comment. - */ - @Preview - @Deprecated - public void submit(String body, GHPullRequestReviewEvent event) throws IOException { - new Requester(owner.root).method("POST") - .with("body", body) - .with("event", event.action()) - .withPreview("application/vnd.github.black-cat-preview+json") - .to(getApiRoute()+"/events",this); - this.body = body; - } - - /** - * Deletes this review. - */ - @Preview - @Deprecated - public void delete() throws IOException { - new Requester(owner.root).method("DELETE") - .withPreview(BLACK_CAT) - .to(getApiRoute()); + GHPullRequestReview wrapUp(GHPullRequest owner) { + this.owner = owner; + return this; } /** * Dismisses this review. */ - @Preview - @Deprecated public void dismiss(String message) throws IOException { new Requester(owner.root).method("PUT") .with("message", message) - .withPreview(BLACK_CAT) - .to(getApiRoute()+"/dismissals"); + .to(getApiRoute() + "/dismissals"); state = GHPullRequestReviewState.DISMISSED; } - - /** - * Obtains all the review comments associated with this pull request review. - */ - @Preview - @Deprecated - public PagedIterable listReviewComments() throws IOException { - return new PagedIterable() { - public PagedIterator _iterator(int pageSize) { - return new PagedIterator( - owner.root.retrieve() - .withPreview(BLACK_CAT) - .asIterator(getApiRoute() + "/comments", - GHPullRequestReviewComment[].class, pageSize)) { - protected void wrapUp(GHPullRequestReviewComment[] page) { - for (GHPullRequestReviewComment c : page) - c.wrapUp(owner); - } - }; - } - }; - } - } diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReviewAbstract.java b/src/main/java/org/kohsuke/github/GHPullRequestReviewAbstract.java new file mode 100644 index 0000000000..4842a62085 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHPullRequestReviewAbstract.java @@ -0,0 +1,101 @@ +/* + * The MIT License + * + * Copyright (c) 2011, Eric Maupin + * + * 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 edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + +import java.io.IOException; +import java.net.URL; + +@SuppressFBWarnings(value = {"UWF_UNWRITTEN_FIELD"}, justification = "JSON API") +public abstract class GHPullRequestReviewAbstract extends GHObject { + protected GHPullRequest owner; + + protected String body; + private GHUser user; + private String commit_id; + + public abstract GHPullRequestReviewState getState(); + + /** + * Gets the pull request to which this review is associated. + */ + public GHPullRequest getParent() { + return owner; + } + + /** + * The comment itself. + */ + public String getBody() { + return body; + } + + /** + * Gets the user who posted this review. + */ + public GHUser getUser() throws IOException { + return owner.root.getUser(user.getLogin()); + } + + public String getCommitId() { + return commit_id; + } + + @Override + public URL getHtmlUrl() { + return null; + } + + String getApiRoute() { + return owner.getApiRoute() + "/reviews/" + id; + } + + /** + * Deletes this review. + */ + public void delete() throws IOException { + new Requester(owner.root).method("DELETE") + .to(getApiRoute()); + } + + /** + * Obtains all the review comments associated with this pull request review. + */ + public PagedIterable listReviewComments() { + return new PagedIterable() { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator( + owner.root.retrieve() + .asIterator(getApiRoute() + "/comments", + GHPullRequestReviewComment[].class, pageSize)) { + protected void wrapUp(GHPullRequestReviewComment[] page) { + for (GHPullRequestReviewComment c : page) + c.wrapUp(owner); + } + }; + } + }; + } +} diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReviewDraft.java b/src/main/java/org/kohsuke/github/GHPullRequestReviewDraft.java new file mode 100644 index 0000000000..689d061bc0 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHPullRequestReviewDraft.java @@ -0,0 +1,53 @@ +/* + * The MIT License + * + * Copyright (c) 2011, Eric Maupin + * + * 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; + +/** + * Draft of a Pull Request review. + * + * @see GHPullRequest#newDraftReview(String, String, GHPullRequestReviewComment...) + */ +public class GHPullRequestReviewDraft extends GHPullRequestReviewAbstract { + + GHPullRequestReviewDraft wrapUp(GHPullRequest owner) { + this.owner = owner; + return this; + } + + @Override + public GHPullRequestReviewState getState() { + return GHPullRequestReviewState.PENDING; + } + + public void submit(String body, GHPullRequestReviewEvent event) throws IOException { + new Requester(owner.root).method("POST") + .with("body", body) + .with("event", event.action()) + .to(getApiRoute() + "/events", this); + this.body = body; + } + +} diff --git a/src/test/java/org/kohsuke/github/PullRequestTest.java b/src/test/java/org/kohsuke/github/PullRequestTest.java index bf45e35c46..97826baea0 100644 --- a/src/test/java/org/kohsuke/github/PullRequestTest.java +++ b/src/test/java/org/kohsuke/github/PullRequestTest.java @@ -33,7 +33,7 @@ public void createPullRequestComment() throws Exception { public void testPullRequestReviews() throws Exception { String name = rnd.next(); GHPullRequest p = getRepository().createPullRequest(name, "stable", "master", "## test"); - GHPullRequestReview draftReview = p.createReview("Some draft review", null, + GHPullRequestReviewDraft draftReview = p.newDraftReview(null, "Some draft review", GHPullRequestReviewComment.draft("Some niggle", "changelog.html", 1) ); assertThat(draftReview.getState(), is(GHPullRequestReviewState.PENDING)); @@ -45,15 +45,15 @@ public void testPullRequestReviews() throws Exception { assertThat(review.getState(), is(GHPullRequestReviewState.PENDING)); assertThat(review.getBody(), is("Some draft review")); assertThat(review.getCommitId(), notNullValue()); - review.submit("Some review comment", GHPullRequestReviewEvent.COMMENT); + draftReview.submit("Some review comment", GHPullRequestReviewEvent.COMMENT); List comments = review.listReviewComments().asList(); assertEquals(1, comments.size()); GHPullRequestReviewComment comment = comments.get(0); assertEquals("Some niggle", comment.getBody()); - review = p.createReview("Some new review", null, + draftReview = p.newDraftReview(null, "Some new review", GHPullRequestReviewComment.draft("Some niggle", "changelog.html", 1) ); - review.delete(); + draftReview.delete(); } @Test From df861f54033c23a976c28639a5e5fdf5d42b4c6e Mon Sep 17 00:00:00 2001 From: Timothy McNally Date: Tue, 9 Jan 2018 17:32:54 -0800 Subject: [PATCH 324/390] Adding methods to GHCreateRepositoryBuilder to allow setting the allowed merge methods for pull requests. --- .../github/GHCreateRepositoryBuilder.java | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHCreateRepositoryBuilder.java b/src/main/java/org/kohsuke/github/GHCreateRepositoryBuilder.java index 492aaf5c81..a11fc4493f 100644 --- a/src/main/java/org/kohsuke/github/GHCreateRepositoryBuilder.java +++ b/src/main/java/org/kohsuke/github/GHCreateRepositoryBuilder.java @@ -21,8 +21,8 @@ public class GHCreateRepositoryBuilder { } public GHCreateRepositoryBuilder description(String description) { - this.builder.with("description",description); - return this; + this.builder.with("description",description); + return this; } public GHCreateRepositoryBuilder homepage(URL homepage) { @@ -74,6 +74,30 @@ public GHCreateRepositoryBuilder autoInit(boolean b) { return this; } + /** + * Allow or disallow squash-merging pull requests. + */ + public GHCreateRepositoryBuilder allowSquashMerge(boolean b) { + this.builder.with("allow_squash_merge",b); + return this; + } + + /** + * Allow or disallow merging pull requests with a merge commit. + */ + public GHCreateRepositoryBuilder allowMergeCommit(boolean b) { + this.builder.with("allow_merge_commit",b); + return this; + } + + /** + * Allow or disallow rebase-merging pull requests. + */ + public GHCreateRepositoryBuilder allowRebaseMerge(boolean b) { + this.builder.with("allow_rebase_merge",b); + return this; + } + /** * Creates a default .gitignore * From d0b4652dcde741edabbf063b8ea6218cf822c46c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20H=C3=A4user?= Date: Mon, 20 Nov 2017 21:36:00 +0100 Subject: [PATCH 325/390] Replace "new Error" with GHException (rolled back some of the hunks from the original PR) --- src/main/java/org/kohsuke/github/GHGist.java | 10 +++------- src/main/java/org/kohsuke/github/Requester.java | 17 +++++++++-------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHGist.java b/src/main/java/org/kohsuke/github/GHGist.java index a9bf3fef42..c4c91737d6 100644 --- a/src/main/java/org/kohsuke/github/GHGist.java +++ b/src/main/java/org/kohsuke/github/GHGist.java @@ -103,7 +103,7 @@ public Map getFiles() { * Used when caller obtains {@link GHGist} without knowing its owner. * A partially constructed owner object is interned. */ - /*package*/ GHGist wrapUp(GitHub root) throws IOException { + /*package*/ GHGist wrapUp(GitHub root) { this.owner = root.getUser(owner); this.root = root; wrapUp(); @@ -144,12 +144,8 @@ public PagedIterator _iterator(int pageSize) { return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("forks"), GHGist[].class, pageSize)) { @Override protected void wrapUp(GHGist[] page) { - try { - for (GHGist c : page) - c.wrapUp(root); - } catch (IOException e) { - throw new Error(e); - } + for (GHGist c : page) + c.wrapUp(root); } }; } diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index 00f11f2426..24063099e6 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -54,16 +54,17 @@ import java.util.Locale; import java.util.Map; import java.util.NoSuchElementException; -import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.GZIPInputStream; -import static java.util.Arrays.*; -import static java.util.logging.Level.*; -import static org.apache.commons.lang.StringUtils.*; -import static org.kohsuke.github.GitHub.*; +import static java.util.Arrays.asList; +import static java.util.logging.Level.FINE; +import static java.util.logging.Level.FINEST; +import static java.util.logging.Level.INFO; +import static org.apache.commons.lang.StringUtils.defaultString; +import static org.kohsuke.github.GitHub.MAPPER; /** * A builder pattern for making HTTP call and parsing its output. @@ -451,8 +452,8 @@ private boolean isMethodWithBody() { try { return new PagingIterator(type, tailApiUrl, root.getApiURL(s.toString())); - } catch (IOException e) { - throw new Error(e); + } catch (MalformedURLException e) { + throw new GHException("Unable to build github Api URL",e); } } @@ -513,7 +514,7 @@ private void fetch() { } } } catch (IOException e) { - throw new Error(e); + throw new GHException(e); } } From a17ce04552ddd3f6bd8210c740184e6c7ad13ae4 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 12 Jan 2018 21:00:25 -0800 Subject: [PATCH 326/390] Adjustment to compensate --- src/main/java/org/kohsuke/github/Requester.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index 24063099e6..f26466bacf 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -452,7 +452,7 @@ private boolean isMethodWithBody() { try { return new PagingIterator(type, tailApiUrl, root.getApiURL(s.toString())); - } catch (MalformedURLException e) { + } catch (IOException e) { throw new GHException("Unable to build github Api URL",e); } } @@ -514,7 +514,7 @@ private void fetch() { } } } catch (IOException e) { - throw new GHException(e); + throw new GHException("Failed to retrieve "+url); } } From 43075faaf82f3afc1105f92d056aad6f46032265 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 12 Jan 2018 21:06:47 -0800 Subject: [PATCH 327/390] By convention we use "listXyz" method names --- src/main/java/org/kohsuke/github/GitHub.java | 7 +++---- src/test/java/org/kohsuke/github/GitHubTest.java | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 1013508c01..f7e0d58096 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -48,7 +48,6 @@ import java.util.Date; import java.util.HashMap; import java.util.HashSet; -import java.util.Hashtable; import java.util.List; import java.util.Map; import java.util.Set; @@ -439,8 +438,8 @@ public GHOrganization getOrganization(String name) throws IOException { /** * Gets a list of all organizations. */ - public PagedIterable getOrganizations() { - return getOrganizations(null); + public PagedIterable listOrganizations() { + return listOrganizations(null); } /** @@ -448,7 +447,7 @@ public PagedIterable getOrganizations() { * * @see List All Orgs - Parameters */ - public PagedIterable getOrganizations(final String since) { + public PagedIterable listOrganizations(final String since) { return new PagedIterable() { @Override public PagedIterator _iterator(int pageSize) { diff --git a/src/test/java/org/kohsuke/github/GitHubTest.java b/src/test/java/org/kohsuke/github/GitHubTest.java index c6e1e4113a..f4b77b8271 100644 --- a/src/test/java/org/kohsuke/github/GitHubTest.java +++ b/src/test/java/org/kohsuke/github/GitHubTest.java @@ -164,7 +164,7 @@ public void getOrgs() throws IOException { GitHub hub = GitHub.connect(); int iterations = 10; Set orgIds = new HashSet(); - for (GHOrganization org : Iterables.limit(hub.getOrganizations().withPageSize(2), iterations)) { + for (GHOrganization org : Iterables.limit(hub.listOrganizations().withPageSize(2), iterations)) { orgIds.add(org.getId()); System.out.println(org.getName()); } From 65996050d5f25c44d1db8792da6c6e605955ab57 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 12 Jan 2018 21:12:40 -0800 Subject: [PATCH 328/390] Massaged changes to follow the convention --- src/main/java/org/kohsuke/github/GHTeam.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHTeam.java b/src/main/java/org/kohsuke/github/GHTeam.java index a2f9a87ae4..bccec4b5ed 100644 --- a/src/main/java/org/kohsuke/github/GHTeam.java +++ b/src/main/java/org/kohsuke/github/GHTeam.java @@ -19,10 +19,16 @@ public class GHTeam { protected /*final*/ GHOrganization org; /** Member's role in a team */ - public enum ROLE { - MEMBER, // A normal member of the team - MAINTAINER // Able to add/remove other team members, promote other team members to team maintainer, and edit the team's name and description. - }; + public enum Role { + /** + * A normal member of the team + */ + MEMBER, + /** + * Able to add/remove other team members, promote other team members to team maintainer, and edit the team's name and description. + */ + MAINTAINER + } /*package*/ GHTeam wrapUp(GHOrganization owner) { this.org = owner; @@ -132,7 +138,7 @@ public void add(GHUser u) throws IOException { * * @throws IOException */ - public void add(GHUser user, ROLE role) throws IOException { + public void add(GHUser user, Role role) throws IOException { org.root.retrieve().method("PUT") .with("role", role.name()) .to(api("/memberships/" + user.getLogin()), null); From 4e31636181a2d847a9c6dbb6c186e387951f86af Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 12 Jan 2018 21:25:30 -0800 Subject: [PATCH 329/390] Allow the caller to wait for the mergeable state to change. This approaches #394 differently. The problem with the original #394 is that the supposed behaviour is only useful for people waiting for `getMergeable()` to return non-null in a busy loop, yet it impacts all the other methods of this object. --- .../java/org/kohsuke/github/GHPullRequest.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index 9342623829..6c8c9aac03 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -182,6 +182,13 @@ public boolean canMaintainerModify() throws IOException { return maintainer_can_modify; } + /** + * Is this PR mergeable? + * + * @return + * null if the state has not been determined yet, for example when a PR is newly created. + * Use {@link #refresh()} after some interval to wait until the value is determined. + */ public Boolean getMergeable() throws IOException { populate(); return mergeable; @@ -217,6 +224,13 @@ public String getMergeCommitSha() throws IOException { */ private void populate() throws IOException { if (mergeable_state!=null) return; // already populated + refresh(); + } + + /** + * Repopulates this object. + */ + public void refresh() throws IOException { if (root.isOffline()) { return; // cannot populate, will have to live with what we have } From 5113aacb89de358ade715a09570396c1d9a7b11e Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 12 Jan 2018 21:28:37 -0800 Subject: [PATCH 330/390] Issue #403: Typo in method name --- src/main/java/org/kohsuke/github/GHRepository.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 4dfd1397bc..b40f387b7f 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -173,6 +173,14 @@ public String getGitTransportUrl() { * Gets the HTTPS URL to this repository, such as "https://github.com/kohsuke/jenkins.git" * This URL is read-only. */ + public String getHttpTransportUrl() { + return clone_url; + } + + /** + * @deprecated + * Typo of {@link #getHttpTransportUrl()} + */ public String gitHttpTransportUrl() { return clone_url; } From 0f7c1604098b8e9d8f92d58d07bd7ec7b2188335 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 12 Jan 2018 21:33:03 -0800 Subject: [PATCH 331/390] Based on issue #399, adjusting the behaviour. This ends up changing the behaviour cloes to that of #394. --- src/main/java/org/kohsuke/github/GHPullRequest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index 6c8c9aac03..742ab24279 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -187,10 +187,12 @@ public boolean canMaintainerModify() throws IOException { * * @return * null if the state has not been determined yet, for example when a PR is newly created. - * Use {@link #refresh()} after some interval to wait until the value is determined. + * If this method is called on an instance whose mergeable state is not yet known, + * API call is made to retrieve the latest state. */ public Boolean getMergeable() throws IOException { - populate(); + if (mergeable==null) + refresh(); return mergeable; } From acbf286e59d92592038e9c0cf56dd91509d93446 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 13 Jan 2018 09:43:44 -0800 Subject: [PATCH 332/390] Massaged the changes - Restored binary compatibility. The draft API has changed in some significant way when it became public, and the PR took the liberty to delete removed constants and method signatures. I brought them back so that older clients can keep functioning. - Introduced a builder pattern to create PR review - replying to a review comment should be an instance method, not a static method. - GHPullRequestReview and GHPullRequestReviewDraft was not making sense to me, since GitHub API doesn't differentiate them. It creates a practical problem of not being able to submit a review comment unless you created the review comment in the same JVM session. That said, I don't understand the point of this two phase approach in the GitHub API to begin with! --- .../org/kohsuke/github/GHPullRequest.java | 89 +------------- .../kohsuke/github/GHPullRequestReview.java | 109 ++++++++++++++++-- .../github/GHPullRequestReviewAbstract.java | 101 ---------------- .../github/GHPullRequestReviewBuilder.java | 91 +++++++++++++++ .../github/GHPullRequestReviewComment.java | 11 ++ .../github/GHPullRequestReviewDraft.java | 53 --------- .../github/GHPullRequestReviewEvent.java | 30 +++-- .../github/GHPullRequestReviewState.java | 32 ++++- .../java/org/kohsuke/github/Previews.java | 1 - .../org/kohsuke/github/PullRequestTest.java | 17 +-- 10 files changed, 265 insertions(+), 269 deletions(-) delete mode 100644 src/main/java/org/kohsuke/github/GHPullRequestReviewAbstract.java create mode 100644 src/main/java/org/kohsuke/github/GHPullRequestReviewBuilder.java delete mode 100644 src/main/java/org/kohsuke/github/GHPullRequestReviewDraft.java diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index 5a62936f8d..084c982133 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -23,16 +23,10 @@ */ package org.kohsuke.github; -import javax.annotation.Nullable; import java.io.IOException; import java.net.URL; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Date; -import java.util.List; - -import static org.kohsuke.github.Previews.*; /** * A pull request. @@ -44,7 +38,6 @@ public class GHPullRequest extends GHIssue { private static final String COMMENTS_ACTION = "/comments"; - private static final String COMMIT_ID_FIELD = "commit_id"; private String patch_url, diff_url, issue_url; private GHCommitPointer base; @@ -298,71 +291,19 @@ protected void wrapUp(GHPullRequestCommitDetail[] page) { }; } - public GHPullRequestReview createReview(@Nullable String commitId, String body, GHPullRequestReviewEvent event, - GHPullRequestReviewComment... comments) throws IOException { - return createReview(commitId, body, event, Arrays.asList(comments)); - } - - public GHPullRequestReview createReview(@Nullable String commitId, String body, GHPullRequestReviewEvent event, - List comments) throws IOException { - List draftComments = toDraftReviewComments(comments); - return new Requester(root).method("POST") - .with(COMMIT_ID_FIELD, commitId) - .with("body", body) - .with("event", event.action()) - ._with("comments", draftComments) - .to(getApiRoute() + "/reviews", GHPullRequestReview.class) - .wrapUp(this); - } - - public GHPullRequestReviewDraft newDraftReview(@Nullable String commitId, String body, GHPullRequestReviewComment... comments) - throws IOException { - return newDraftReview(commitId, body, Arrays.asList(comments)); - } - - public GHPullRequestReviewDraft newDraftReview(@Nullable String commitId, String body, List comments) - throws IOException { - List draftComments = toDraftReviewComments(comments); - return new Requester(root).method("POST") - .with(COMMIT_ID_FIELD, commitId) - .with("body", body) - ._with("comments", draftComments) - .to(getApiRoute() + "/reviews", GHPullRequestReviewDraft.class) - .wrapUp(this); - } - - private static List toDraftReviewComments(List comments) { - List draftComments = new ArrayList(comments.size()); - for (GHPullRequestReviewComment c : comments) { - Integer position = c.getPosition(); - if (position == null) { - throw new IllegalArgumentException("GHPullRequestReviewComment must have a position"); - } - draftComments.add(new DraftReviewComment(c.getBody(), c.getPath(), position)); - } - return draftComments; + public GHPullRequestReviewBuilder createReview() { + return new GHPullRequestReviewBuilder(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_FIELD, sha) + .with("commit_id", sha) .with("path", path) .with("position", position) .to(getApiRoute() + COMMENTS_ACTION, GHPullRequestReviewComment.class).wrapUp(this); } - /** - * Create a reply to the current comment. - */ - public GHPullRequestReviewComment createReviewCommentReply(GHPullRequestReviewComment comment, String body) throws IOException { - return new Requester(owner.root).method("POST") - .with("body", body) - .with("in_reply_to", comment.getId()) - .to(getApiRoute() + COMMENTS_ACTION, GHPullRequestReviewComment.class) - .wrapUp(this); - } - /** * Merge this pull request. * @@ -415,28 +356,4 @@ private void fetchIssue() throws IOException { fetchedIssueDetails = true; } } - - private static class DraftReviewComment { - private String body; - private String path; - private int position; - - public DraftReviewComment(String body, String path, int position) { - this.body = body; - this.path = path; - this.position = position; - } - - public String getBody() { - return body; - } - - public String getPath() { - return path; - } - - public int getPosition() { - return position; - } - } } diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReview.java b/src/main/java/org/kohsuke/github/GHPullRequestReview.java index 3bb155b881..45b6c044d9 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestReview.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestReview.java @@ -23,26 +23,98 @@ */ package org.kohsuke.github; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + +import javax.annotation.CheckForNull; import java.io.IOException; -import java.util.List; +import java.net.URL; /** - * Review to the pull request + * Review to a pull request. * * @see GHPullRequest#listReviews() - * @see GHPullRequest#createReview(String, String, GHPullRequestReviewEvent, List) + * @see GHPullRequestReviewBuilder */ -public class GHPullRequestReview extends GHPullRequestReviewAbstract { +@SuppressFBWarnings(value = {"UWF_UNWRITTEN_FIELD"}, justification = "JSON API") +public class GHPullRequestReview extends GHObject { + GHPullRequest owner; + + private String body; + private GHUser user; + private String commit_id; private GHPullRequestReviewState state; - @Override + /*package*/ GHPullRequestReview wrapUp(GHPullRequest owner) { + this.owner = owner; + return this; + } + + /** + * Gets the pull request to which this review is associated. + */ + public GHPullRequest getParent() { + return owner; + } + + /** + * The comment itself. + */ + public String getBody() { + return body; + } + + /** + * Gets the user who posted this review. + */ + public GHUser getUser() throws IOException { + return owner.root.getUser(user.getLogin()); + } + + public String getCommitId() { + return commit_id; + } + + @CheckForNull public GHPullRequestReviewState getState() { return state; } - GHPullRequestReview wrapUp(GHPullRequest owner) { - this.owner = owner; - return this; + @Override + public URL getHtmlUrl() { + return null; + } + + protected String getApiRoute() { + return owner.getApiRoute()+"/reviews/"+id; + } + + /** + * @deprecated + * Former preview method that changed when it got public. Left here for backward compatibility. + * Use {@link #submit(String, GHPullRequestReviewEvent)} + */ + public void submit(String body, GHPullRequestReviewState state) throws IOException { + submit(body,state.toEvent()); + } + + /** + * Updates the comment. + */ + public void submit(String body, GHPullRequestReviewEvent event) throws IOException { + new Requester(owner.root).method("POST") + .with("body", body) + .with("event", event.action()) + .to(getApiRoute()+"/events",this); + this.body = body; + this.state = event.toState(); + } + + /** + * Deletes this review. + */ + public void delete() throws IOException { + new Requester(owner.root).method("DELETE") + .to(getApiRoute()); } /** @@ -51,7 +123,26 @@ GHPullRequestReview wrapUp(GHPullRequest owner) { public void dismiss(String message) throws IOException { new Requester(owner.root).method("PUT") .with("message", message) - .to(getApiRoute() + "/dismissals"); + .to(getApiRoute()+"/dismissals"); state = GHPullRequestReviewState.DISMISSED; } + + /** + * Obtains all the review comments associated with this pull request review. + */ + public PagedIterable listReviewComments() throws IOException { + return new PagedIterable() { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator( + owner.root.retrieve() + .asIterator(getApiRoute() + "/comments", + GHPullRequestReviewComment[].class, pageSize)) { + protected void wrapUp(GHPullRequestReviewComment[] page) { + for (GHPullRequestReviewComment c : page) + c.wrapUp(owner); + } + }; + } + }; + } } diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReviewAbstract.java b/src/main/java/org/kohsuke/github/GHPullRequestReviewAbstract.java deleted file mode 100644 index 4842a62085..0000000000 --- a/src/main/java/org/kohsuke/github/GHPullRequestReviewAbstract.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2011, Eric Maupin - * - * 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 edu.umd.cs.findbugs.annotations.SuppressFBWarnings; - -import java.io.IOException; -import java.net.URL; - -@SuppressFBWarnings(value = {"UWF_UNWRITTEN_FIELD"}, justification = "JSON API") -public abstract class GHPullRequestReviewAbstract extends GHObject { - protected GHPullRequest owner; - - protected String body; - private GHUser user; - private String commit_id; - - public abstract GHPullRequestReviewState getState(); - - /** - * Gets the pull request to which this review is associated. - */ - public GHPullRequest getParent() { - return owner; - } - - /** - * The comment itself. - */ - public String getBody() { - return body; - } - - /** - * Gets the user who posted this review. - */ - public GHUser getUser() throws IOException { - return owner.root.getUser(user.getLogin()); - } - - public String getCommitId() { - return commit_id; - } - - @Override - public URL getHtmlUrl() { - return null; - } - - String getApiRoute() { - return owner.getApiRoute() + "/reviews/" + id; - } - - /** - * Deletes this review. - */ - public void delete() throws IOException { - new Requester(owner.root).method("DELETE") - .to(getApiRoute()); - } - - /** - * Obtains all the review comments associated with this pull request review. - */ - public PagedIterable listReviewComments() { - return new PagedIterable() { - public PagedIterator _iterator(int pageSize) { - return new PagedIterator( - owner.root.retrieve() - .asIterator(getApiRoute() + "/comments", - GHPullRequestReviewComment[].class, pageSize)) { - protected void wrapUp(GHPullRequestReviewComment[] page) { - for (GHPullRequestReviewComment c : page) - c.wrapUp(owner); - } - }; - } - }; - } -} diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReviewBuilder.java b/src/main/java/org/kohsuke/github/GHPullRequestReviewBuilder.java new file mode 100644 index 0000000000..625f6bd923 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHPullRequestReviewBuilder.java @@ -0,0 +1,91 @@ +package org.kohsuke.github; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * Builds up a creation of new {@link GHPullRequestReview}. + * + * @author Kohsuke Kawaguchi + * @see GHPullRequest#createReview() + */ +public class GHPullRequestReviewBuilder { + private final GHPullRequest pr; + private final Requester builder; + private final List comments = new ArrayList(); + + /*package*/ GHPullRequestReviewBuilder(GHPullRequest pr) { + this.pr = pr; + this.builder = new Requester(pr.root); + } + + // public GHPullRequestReview createReview(@Nullable String commitId, String body, GHPullRequestReviewEvent event, + // List comments) throws IOException + + /** + * The SHA of the commit that needs a review. Not using the latest commit SHA may render your review comment outdated if a subsequent commit modifies the line you specify as the position. Defaults to the most recent commit in the pull request when you do not specify a value. + */ + public GHPullRequestReviewBuilder commitId(String commitId) { + builder.with("commit_id",commitId); + return this; + } + + /** + * Required when using REQUEST_CHANGES or COMMENT for the event parameter. The body text of the pull request review. + */ + public GHPullRequestReviewBuilder body(String body) { + builder.with("body",body); + return this; + } + + /** + * The review action you want to perform. The review actions include: APPROVE, REQUEST_CHANGES, or COMMENT. + * By leaving this blank, you set the review action state to PENDING, + * which means you will need to {@linkplain GHPullRequestReview#submit() submit the pull request review} when you are ready. + */ + public GHPullRequestReviewBuilder event(GHPullRequestReviewEvent event) { + builder.with("event",event.action()); + return this; + } + + /** + * @param body The relative path to the file that necessitates a review comment. + * @param path The position in the diff where you want to add a review comment. Note this value is not the same as the line number in the file. For help finding the position value, read the note below. + * @param position Text of the review comment. + */ + public GHPullRequestReviewBuilder comment(String body, String path, int position) { + comments.add(new DraftReviewComment(body,path,position)); + return this; + } + + public GHPullRequestReview create() throws IOException { + return builder.method("POST")._with("comments",comments) + .to(pr.getApiRoute() + "/reviews", GHPullRequestReview.class) + .wrapUp(pr); + } + + private static class DraftReviewComment { + private String body; + private String path; + private int position; + + DraftReviewComment(String body, String path, int position) { + this.body = body; + this.path = path; + this.position = position; + } + + public String getBody() { + return body; + } + + public String getPath() { + return path; + } + + public int getPosition() { + return position; + } + } +} diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java b/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java index 5ab8861f8d..811e15a4fc 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java @@ -124,6 +124,17 @@ public void delete() throws IOException { new Requester(owner.root).method("DELETE").to(getApiRoute()); } + /** + * Create a new comment that replies to this comment. + */ + public GHPullRequestReviewComment reply(String body) throws IOException { + return new Requester(owner.root).method("POST") + .with("body", body) + .with("in_reply_to", getId()) + .to(getApiRoute() + "/comments", GHPullRequestReviewComment.class) + .wrapUp(owner); + } + @Preview @Deprecated public GHReaction createReaction(ReactionContent content) throws IOException { return new Requester(owner.root) diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReviewDraft.java b/src/main/java/org/kohsuke/github/GHPullRequestReviewDraft.java deleted file mode 100644 index 689d061bc0..0000000000 --- a/src/main/java/org/kohsuke/github/GHPullRequestReviewDraft.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * The MIT License - * - * Copyright (c) 2011, Eric Maupin - * - * 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; - -/** - * Draft of a Pull Request review. - * - * @see GHPullRequest#newDraftReview(String, String, GHPullRequestReviewComment...) - */ -public class GHPullRequestReviewDraft extends GHPullRequestReviewAbstract { - - GHPullRequestReviewDraft wrapUp(GHPullRequest owner) { - this.owner = owner; - return this; - } - - @Override - public GHPullRequestReviewState getState() { - return GHPullRequestReviewState.PENDING; - } - - public void submit(String body, GHPullRequestReviewEvent event) throws IOException { - new Requester(owner.root).method("POST") - .with("body", body) - .with("event", event.action()) - .to(getApiRoute() + "/events", this); - this.body = body; - } - -} diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReviewEvent.java b/src/main/java/org/kohsuke/github/GHPullRequestReviewEvent.java index 4a5d66094f..e6537e0f09 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestReviewEvent.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestReviewEvent.java @@ -23,19 +23,29 @@ */ package org.kohsuke.github; +/** + * Action to perform on {@link GHPullRequestReview}. + */ public enum GHPullRequestReviewEvent { - PENDING(null), - APPROVE("APPROVE"), - REQUEST_CHANGES("REQUEST_CHANGES"), - COMMENT("COMMENT"); - - private final String _action; + PENDING, + APPROVE, + REQUEST_CHANGES, + COMMENT; - GHPullRequestReviewEvent(String action) { - _action = action; + /*package*/ String action() { + return this==PENDING ? null : name(); } - public String action() { - return _action; + /** + * When a {@link GHPullRequestReview} is submitted with this event, it should transition to this state. + */ + /*package*/ GHPullRequestReviewState toState() { + switch (this) { + case PENDING: return GHPullRequestReviewState.PENDING; + case APPROVE: return GHPullRequestReviewState.APPROVED; + case REQUEST_CHANGES: return GHPullRequestReviewState.CHANGES_REQUESTED; + case COMMENT: return GHPullRequestReviewState.COMMENTED; + } + throw new IllegalStateException(); } } diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReviewState.java b/src/main/java/org/kohsuke/github/GHPullRequestReviewState.java index eff7fbf60b..a64a105994 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestReviewState.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestReviewState.java @@ -1,9 +1,39 @@ package org.kohsuke.github; +/** + * Current state of {@link GHPullRequestReview} + */ public enum GHPullRequestReviewState { PENDING, APPROVED, CHANGES_REQUESTED, + /** + * @deprecated + * This was the thing when this API was in preview, but it changed when it became public. + * Use {@link #CHANGES_REQUESTED}. Left here for compatibility. + */ + REQUEST_CHANGES, COMMENTED, - DISMISSED + DISMISSED; + + /** + * @deprecated + * This was an internal method accidentally exposed. + * Left here for compatibility. + */ + public String action() { + GHPullRequestReviewEvent e = toEvent(); + return e==null ? null : e.action(); + } + + /*package*/ GHPullRequestReviewEvent toEvent() { + switch (this) { + case PENDING: return GHPullRequestReviewEvent.PENDING; + case APPROVED: return GHPullRequestReviewEvent.APPROVE; + case CHANGES_REQUESTED: return GHPullRequestReviewEvent.REQUEST_CHANGES; + case REQUEST_CHANGES: return GHPullRequestReviewEvent.REQUEST_CHANGES; + case COMMENTED: return GHPullRequestReviewEvent.COMMENT; + } + return null; + } } diff --git a/src/main/java/org/kohsuke/github/Previews.java b/src/main/java/org/kohsuke/github/Previews.java index 2bc6dccbc8..3f98c3d4b9 100644 --- a/src/main/java/org/kohsuke/github/Previews.java +++ b/src/main/java/org/kohsuke/github/Previews.java @@ -8,5 +8,4 @@ static final String DRAX = "application/vnd.github.drax-preview+json"; static final String SQUIRREL_GIRL = "application/vnd.github.squirrel-girl-preview"; static final String CLOAK = "application/vnd.github.cloak-preview"; - static final String BLACK_CAT = "application/vnd.github.black-cat-preview+json"; } diff --git a/src/test/java/org/kohsuke/github/PullRequestTest.java b/src/test/java/org/kohsuke/github/PullRequestTest.java index 97826baea0..c2a6a2705e 100644 --- a/src/test/java/org/kohsuke/github/PullRequestTest.java +++ b/src/test/java/org/kohsuke/github/PullRequestTest.java @@ -7,8 +7,7 @@ import java.util.Collection; import java.util.List; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.CoreMatchers.*; /** * @author Kohsuke Kawaguchi @@ -33,9 +32,10 @@ public void createPullRequestComment() throws Exception { public void testPullRequestReviews() throws Exception { String name = rnd.next(); GHPullRequest p = getRepository().createPullRequest(name, "stable", "master", "## test"); - GHPullRequestReviewDraft draftReview = p.newDraftReview(null, "Some draft review", - GHPullRequestReviewComment.draft("Some niggle", "changelog.html", 1) - ); + GHPullRequestReview draftReview = p.createReview() + .body("Some draft review") + .comment("Some niggle", "changelog.html", 1) + .create(); assertThat(draftReview.getState(), is(GHPullRequestReviewState.PENDING)); assertThat(draftReview.getBody(), is("Some draft review")); assertThat(draftReview.getCommitId(), notNullValue()); @@ -50,9 +50,10 @@ public void testPullRequestReviews() throws Exception { assertEquals(1, comments.size()); GHPullRequestReviewComment comment = comments.get(0); assertEquals("Some niggle", comment.getBody()); - draftReview = p.newDraftReview(null, "Some new review", - GHPullRequestReviewComment.draft("Some niggle", "changelog.html", 1) - ); + draftReview = p.createReview() + .body("Some new review") + .comment("Some niggle", "changelog.html", 1) + .create(); draftReview.delete(); } From f41da19db557aaef65b24bec1333d52aeb87061a Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 13 Jan 2018 09:54:14 -0800 Subject: [PATCH 333/390] Further restoration of the compatibility --- .../org/kohsuke/github/GHPullRequest.java | 25 +++++++++++++++++++ .../github/GHPullRequestReviewComment.java | 17 +++++++------ 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index 4e9f1e7e93..b5f02b964c 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -23,10 +23,13 @@ */ package org.kohsuke.github; +import javax.annotation.CheckForNull; import java.io.IOException; import java.net.URL; +import java.util.Arrays; import java.util.Collection; import java.util.Date; +import java.util.List; /** * A pull request. @@ -307,6 +310,28 @@ protected void wrapUp(GHPullRequestCommitDetail[] page) { }; } + /** + * @deprecated + * Use {@link #createReview()} + */ + public GHPullRequestReview createReview(String body, @CheckForNull GHPullRequestReviewState event, + GHPullRequestReviewComment... comments) throws IOException { + return createReview(body, event, Arrays.asList(comments)); + } + + /** + * @deprecated + * Use {@link #createReview()} + */ + public GHPullRequestReview createReview(String body, @CheckForNull GHPullRequestReviewState event, + List comments) throws IOException { + GHPullRequestReviewBuilder b = createReview().body(body); + for (GHPullRequestReviewComment c : comments) { + b.comment(c.getBody(), c.getPath(), c.getPosition()); + } + return b.create(); + } + public GHPullRequestReviewBuilder createReview() { return new GHPullRequestReviewBuilder(this); } diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java b/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java index 811e15a4fc..5cda4abb0a 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestReviewComment.java @@ -47,6 +47,10 @@ public class GHPullRequestReviewComment extends GHObject implements Reactable { private long in_reply_to_id = -1L; + /** + * @deprecated + * You should be using {@link GHPullRequestReviewBuilder#comment(String, String, int)} + */ public static GHPullRequestReviewComment draft(String body, String path, int position) { GHPullRequestReviewComment result = new GHPullRequestReviewComment(); result.body = body; @@ -86,18 +90,17 @@ public String getPath() { } @CheckForNull - public Integer getPosition() { - return position == -1 ? null : position; + public int getPosition() { + return position; } - @CheckForNull - public Integer getOriginalPosition() { - return original_position == -1 ? null : original_position; + public int getOriginalPosition() { + return original_position; } @CheckForNull - public Long getInReplyToId() { - return in_reply_to_id == -1 ? null : in_reply_to_id; + public long getInReplyToId() { + return in_reply_to_id; } @Override From e10b747d6a241dc404d42a818dafffa1dbf2c195 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 13 Jan 2018 10:30:48 -0800 Subject: [PATCH 334/390] Re-retried the object. It looks like the format has changed a bit since this payload was retrieved originally? --- .../java/org/kohsuke/github/GHEventPayloadTest.java | 4 ++-- .../GHEventPayloadTest/pull_request_review.json | 12 +++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/test/java/org/kohsuke/github/GHEventPayloadTest.java b/src/test/java/org/kohsuke/github/GHEventPayloadTest.java index d2ff30012f..71f9fd3e68 100644 --- a/src/test/java/org/kohsuke/github/GHEventPayloadTest.java +++ b/src/test/java/org/kohsuke/github/GHEventPayloadTest.java @@ -193,8 +193,8 @@ public void pull_request_review() throws Exception { GitHub.offline().parseEventPayload(payload.asReader(), GHEventPayload.PullRequestReview.class); assertThat(event.getAction(), is("submitted")); - assertThat(event.getReview().getId(), is(2626884)); - assertThat(event.getReview().getBody(), is("Looks great!")); + assertThat(event.getReview().getId(), is(2626884L)); + assertThat(event.getReview().getBody(), is("Looks great!\n")); assertThat(event.getReview().getState(), is(GHPullRequestReviewState.APPROVED)); assertThat(event.getPullRequest().getNumber(), is(8)); diff --git a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/pull_request_review.json b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/pull_request_review.json index 82c8396086..dd6698c3ac 100644 --- a/src/test/resources/org/kohsuke/github/GHEventPayloadTest/pull_request_review.json +++ b/src/test/resources/org/kohsuke/github/GHEventPayloadTest/pull_request_review.json @@ -5,7 +5,7 @@ "user": { "login": "baxterthehacker", "id": 6752317, - "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", + "avatar_url": "https://avatars3.githubusercontent.com/u/6752317?v=4", "gravatar_id": "", "url": "https://api.github.com/users/baxterthehacker", "html_url": "https://github.com/baxterthehacker", @@ -21,11 +21,11 @@ "type": "User", "site_admin": false }, - "body": "Looks great!", - "submitted_at": "2016-10-03T23:39:09Z", - "state": "approved", + "body": "Looks great!\n", + "state": "APPROVED", "html_url": "https://github.com/baxterthehacker/public-repo/pull/8#pullrequestreview-2626884", "pull_request_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/8", + "author_association": "OWNER", "_links": { "html": { "href": "https://github.com/baxterthehacker/public-repo/pull/8#pullrequestreview-2626884" @@ -33,7 +33,9 @@ "pull_request": { "href": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/8" } - } + }, + "submitted_at": "2016-10-03T23:39:09Z", + "commit_id": "b7a1f9c27caa4e03c14a88feb56e2d4f7500aa63" }, "pull_request": { "url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls/8", From 188245fa7fbf09048df6c57d1763353ca24f94ad Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 13 Jan 2018 10:36:45 -0800 Subject: [PATCH 335/390] [maven-release-plugin] prepare release github-api-1.91 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index a941d38b75..1d7427dbb2 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.91-SNAPSHOT + 1.91 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - HEAD + github-api-1.91 From cdf6f18ec0afd9bf80a23e2452a29a72b05fd382 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 13 Jan 2018 10:36:53 -0800 Subject: [PATCH 336/390] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 1d7427dbb2..14ee9b4ed3 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.91 + 1.92-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - github-api-1.91 + HEAD From 0e5ffda5e5b678e5a54fa2c6f2d86b51e25e948f Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 13 Jan 2018 11:45:57 -0800 Subject: [PATCH 337/390] Release failed due to javadoc errors --- .../java/org/kohsuke/github/GHPullRequestReviewBuilder.java | 2 +- src/main/java/org/kohsuke/github/RateLimitHandler.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHPullRequestReviewBuilder.java b/src/main/java/org/kohsuke/github/GHPullRequestReviewBuilder.java index 625f6bd923..318daf721f 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestReviewBuilder.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestReviewBuilder.java @@ -42,7 +42,7 @@ public GHPullRequestReviewBuilder body(String body) { /** * The review action you want to perform. The review actions include: APPROVE, REQUEST_CHANGES, or COMMENT. * By leaving this blank, you set the review action state to PENDING, - * which means you will need to {@linkplain GHPullRequestReview#submit() submit the pull request review} when you are ready. + * which means you will need to {@linkplain GHPullRequestReview#submit(String, GHPullRequestReviewEvent) submit the pull request review} when you are ready. */ public GHPullRequestReviewBuilder event(GHPullRequestReviewEvent event) { builder.with("event",event.action()); diff --git a/src/main/java/org/kohsuke/github/RateLimitHandler.java b/src/main/java/org/kohsuke/github/RateLimitHandler.java index 053fd783e0..e5351da541 100644 --- a/src/main/java/org/kohsuke/github/RateLimitHandler.java +++ b/src/main/java/org/kohsuke/github/RateLimitHandler.java @@ -37,7 +37,7 @@ public abstract class RateLimitHandler { public void onError(IOException e, HttpURLConnection uc) throws IOException { try { Thread.sleep(parseWaitTime(uc)); - } catch (InterruptedException _) { + } catch (InterruptedException x) { throw (InterruptedIOException)new InterruptedIOException().initCause(e); } } From 24e288d5840b600fd0bd44cc3bef0180d990bc61 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 13 Jan 2018 11:51:56 -0800 Subject: [PATCH 338/390] [maven-release-plugin] prepare release github-api-1.92 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 14ee9b4ed3..b8138797e4 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.92-SNAPSHOT + 1.92 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - HEAD + github-api-1.92 From 192e21a9fcacf4dffc975156bcf5e8ff7bf297b1 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sat, 13 Jan 2018 11:52:05 -0800 Subject: [PATCH 339/390] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index b8138797e4..500136edab 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.92 + 1.93-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - github-api-1.92 + HEAD From 3503ff6d3665c6065c9e38aadeeaad61cd2a05bb Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sun, 21 Jan 2018 11:50:22 -0800 Subject: [PATCH 340/390] Additional methods for issue comment --- .../github/GHCommentAuthorAssociation.java | 37 +++++++++++++++++++ .../org/kohsuke/github/GHIssueComment.java | 11 +++--- 2 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 src/main/java/org/kohsuke/github/GHCommentAuthorAssociation.java diff --git a/src/main/java/org/kohsuke/github/GHCommentAuthorAssociation.java b/src/main/java/org/kohsuke/github/GHCommentAuthorAssociation.java new file mode 100644 index 0000000000..d66b8d8550 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHCommentAuthorAssociation.java @@ -0,0 +1,37 @@ +package org.kohsuke.github; + +/** + * How is an user associated with a repository? + * + * @author Kohsuke Kawaguchi + */ +public enum GHCommentAuthorAssociation { + /** + * Author has been invited to collaborate on the repository. + */ + COLLABORATOR, + /** + * Author has previously committed to the repository. + */ + CONTRIBUTOR, + /** + * Author has not previously committed to GitHub. + */ + FIRST_TIMER, + /** + * Author has not previously committed to the repository. + */ + FIRST_TIME_CONTRIBUTOR, + /** + * Author is a member of the organization that owns the repository. + */ + MEMBER, + /** + * Author has no association with the repository. + */ + NONE, + /** + * Author is the owner of the repository. + */ + OWNER +} diff --git a/src/main/java/org/kohsuke/github/GHIssueComment.java b/src/main/java/org/kohsuke/github/GHIssueComment.java index 3f4d70643d..3bc2d75b1d 100644 --- a/src/main/java/org/kohsuke/github/GHIssueComment.java +++ b/src/main/java/org/kohsuke/github/GHIssueComment.java @@ -36,7 +36,7 @@ public class GHIssueComment extends GHObject implements Reactable { GHIssue owner; - private String body, gravatar_id; + private String body, gravatar_id, html_url, author_association; private GHUser user; // not fully populated. beware. /*package*/ GHIssueComment wrapUp(GHIssue owner) { @@ -73,12 +73,13 @@ public GHUser getUser() throws IOException { return owner == null || owner.root.isOffline() ? user : owner.root.getUser(user.getLogin()); } - /** - * @deprecated This object has no HTML URL. - */ @Override public URL getHtmlUrl() { - return null; + return GitHub.parseURL(html_url); + } + + public GHCommentAuthorAssociation getAuthorAssociation() { + return GHCommentAuthorAssociation.valueOf(author_association); } /** From e7b76bfdc5f2e44eec4a7f1245db88f24ed272d1 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sun, 21 Jan 2018 11:51:04 -0800 Subject: [PATCH 341/390] Doc improvements --- src/main/java/org/kohsuke/github/GHIssueComment.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHIssueComment.java b/src/main/java/org/kohsuke/github/GHIssueComment.java index 3bc2d75b1d..1b7eea5ebc 100644 --- a/src/main/java/org/kohsuke/github/GHIssueComment.java +++ b/src/main/java/org/kohsuke/github/GHIssueComment.java @@ -32,6 +32,8 @@ * Comment to the issue * * @author Kohsuke Kawaguchi + * @see GHIssue#comment(String) + * @see GHIssue#listComments() */ public class GHIssueComment extends GHObject implements Reactable { GHIssue owner; From 8b38a20c1849606103dd4f676d5c27613df0b7d8 Mon Sep 17 00:00:00 2001 From: Charlie Briggs Date: Tue, 23 Jan 2018 11:00:58 +0000 Subject: [PATCH 342/390] Update commons-lang to 3.7 This fixes the vulnerabilities: * https://issues.apache.org/jira/browse/LANG-1373 * https://issues.apache.org/jira/browse/LANG-805. --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 500136edab..eb71304506 100644 --- a/pom.xml +++ b/pom.xml @@ -96,9 +96,9 @@ - commons-lang - commons-lang - 2.6 + org.apache.commons + commons-lang3 + 3.7 commons-codec From 75918c59cc69dd08653bfbd13d8cb965f972f494 Mon Sep 17 00:00:00 2001 From: Tad Fisher Date: Mon, 5 Feb 2018 14:30:24 -0800 Subject: [PATCH 343/390] Add GHRepository.getRelease and GHRepository.getReleaseByTagName These implement the API endpoints for: - GET /repos/:owner/:repo/releases/:id - GET /repos/:owner/:repo/releases/tags/:tag --- .../java/org/kohsuke/github/GHRepository.java | 16 ++++++++++ .../org/kohsuke/github/RepositoryTest.java | 30 +++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index b40f387b7f..6247e99138 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -310,6 +310,22 @@ public GHRef createRef(String name, String sha) throws IOException { public List getReleases() throws IOException { return listReleases().asList(); } + + public GHRelease getRelease(long id) throws IOException { + try { + return root.retrieve().to(getApiTailUrl("releases/" + id), GHRelease.class).wrap(this); + } catch (FileNotFoundException e) { + return null; // no release for this id + } + } + + public GHRelease getReleaseByTagName(String tag) throws IOException { + try { + return root.retrieve().to(getApiTailUrl("releases/tags/" + tag), GHRelease.class).wrap(this); + } catch (FileNotFoundException e) { + return null; // no release for this tag + } + } public GHRelease getLatestRelease() throws IOException { try { diff --git a/src/test/java/org/kohsuke/github/RepositoryTest.java b/src/test/java/org/kohsuke/github/RepositoryTest.java index 728f94a834..66fe689507 100644 --- a/src/test/java/org/kohsuke/github/RepositoryTest.java +++ b/src/test/java/org/kohsuke/github/RepositoryTest.java @@ -94,6 +94,36 @@ public void LatestRepositoryNotExist() { } } + @Test public void listReleases() throws IOException { + PagedIterable releases = gitHub.getOrganization("github").getRepository("hub").listReleases(); + assertTrue(releases.iterator().hasNext()); + } + + @Test + public void getReleaseExists() throws IOException { + GHRelease release = gitHub.getOrganization("github").getRepository("hub").getRelease(6839710); + assertEquals("v2.3.0-pre10", release.getTagName()); + } + + @Test + public void getReleaseDoesNotExist() throws IOException { + GHRelease release = gitHub.getOrganization("github").getRepository("hub").getRelease(Long.MAX_VALUE); + assertNull(release); + } + + @Test + public void getReleaseByTagNameExists() throws IOException { + GHRelease release = gitHub.getOrganization("github").getRepository("hub").getReleaseByTagName("v2.3.0-pre10"); + assertNotNull(release); + assertEquals("v2.3.0-pre10", release.getTagName()); + } + + @Test + public void getReleaseByTagNameDoesNotExist() throws IOException { + GHRelease release = getRepository().getReleaseByTagName("foo-bar-baz"); + assertNull(release); + } + private GHRepository getRepository() throws IOException { return gitHub.getOrganization("github-api-test-org").getRepository("jenkins"); } From 2497ac68d1469520eb30703c8d2cd8343e26a458 Mon Sep 17 00:00:00 2001 From: Edem Osmanov Date: Wed, 14 Feb 2018 12:16:01 +0200 Subject: [PATCH 344/390] fix issues --- pom.xml | 4 ++-- src/main/java/org/kohsuke/github/GHDeployKey.java | 4 ++-- .../org/kohsuke/github/GHDeploymentStatusBuilder.java | 4 ++-- src/main/java/org/kohsuke/github/GHEventInfo.java | 2 +- src/main/java/org/kohsuke/github/GHObject.java | 8 ++++---- src/main/java/org/kohsuke/github/GHRepository.java | 4 ++-- src/test/java/org/kohsuke/github/AppTest.java | 2 +- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/pom.xml b/pom.xml index b54c58bc47..5f7a2d948c 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.67 + 1.67-tc GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -35,7 +35,7 @@ com.infradna.tool bridge-method-injector - 1.14 + 1.18 diff --git a/src/main/java/org/kohsuke/github/GHDeployKey.java b/src/main/java/org/kohsuke/github/GHDeployKey.java index eb2c2c00fb..5d4ce69589 100644 --- a/src/main/java/org/kohsuke/github/GHDeployKey.java +++ b/src/main/java/org/kohsuke/github/GHDeployKey.java @@ -8,10 +8,10 @@ public class GHDeployKey { protected String url, key, title; protected boolean verified; - protected int id; + protected long id; private GHRepository owner; - public int getId() { + public long getId() { return id; } diff --git a/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java b/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java index 4310153800..57ebcb02bc 100644 --- a/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java +++ b/src/main/java/org/kohsuke/github/GHDeploymentStatusBuilder.java @@ -5,9 +5,9 @@ public class GHDeploymentStatusBuilder { private final Requester builder; private GHRepository repo; - private int deploymentId; + private long deploymentId; - public GHDeploymentStatusBuilder(GHRepository repo, int deploymentId, GHDeploymentState state) { + public GHDeploymentStatusBuilder(GHRepository repo, long deploymentId, GHDeploymentState state) { this.repo = repo; this.deploymentId = deploymentId; this.builder = new Requester(repo.root); diff --git a/src/main/java/org/kohsuke/github/GHEventInfo.java b/src/main/java/org/kohsuke/github/GHEventInfo.java index 09db42aa0f..aab75c1d18 100644 --- a/src/main/java/org/kohsuke/github/GHEventInfo.java +++ b/src/main/java/org/kohsuke/github/GHEventInfo.java @@ -28,7 +28,7 @@ public class GHEventInfo { * Inside the event JSON model, GitHub uses a slightly different format. */ public static class GHEventRepository { - private int id; + private long id; private String url; // repository API URL private String name; // owner/repo } diff --git a/src/main/java/org/kohsuke/github/GHObject.java b/src/main/java/org/kohsuke/github/GHObject.java index 914f1280d3..344dfd9484 100644 --- a/src/main/java/org/kohsuke/github/GHObject.java +++ b/src/main/java/org/kohsuke/github/GHObject.java @@ -11,7 +11,7 @@ */ public abstract class GHObject { protected String url; - protected int id; + protected long id; protected String created_at; protected String updated_at; @@ -54,12 +54,12 @@ public Date getUpdatedAt() throws IOException { /** * Unique ID number of this resource. */ - @WithBridgeMethods(value=String.class, adapterMethod="intToString") - public int getId() { + @WithBridgeMethods(value=String.class, adapterMethod="longToString") + public long getId() { return id; } - private Object intToString(int id, Class type) { + private Object longToString(long id, Class type) { return String.valueOf(id); } diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index e4459e84d6..b00d3b221c 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -69,7 +69,7 @@ public GHDeploymentBuilder createDeployment(String ref) { return new GHDeploymentBuilder(this,ref); } - public PagedIterable getDeploymentStatuses(final int id) { + public PagedIterable getDeploymentStatuses(final long id) { return new PagedIterable() { public PagedIterator iterator() { return new PagedIterator(root.retrieve().asIterator(getApiTailUrl("deployments")+"/"+id+"/statuses", GHDeploymentStatus[].class)) { @@ -114,7 +114,7 @@ private String getParam(String name, String value) { return StringUtils.trimToNull(value)== null? null: name+"="+value; } - public GHDeploymentStatusBuilder createDeployStatus(int deploymentId, GHDeploymentState ghDeploymentState) { + public GHDeploymentStatusBuilder createDeployStatus(long deploymentId, GHDeploymentState ghDeploymentState) { return new GHDeploymentStatusBuilder(this,deploymentId,ghDeploymentState); } diff --git a/src/test/java/org/kohsuke/github/AppTest.java b/src/test/java/org/kohsuke/github/AppTest.java index 5cdb17e987..49396b37f1 100755 --- a/src/test/java/org/kohsuke/github/AppTest.java +++ b/src/test/java/org/kohsuke/github/AppTest.java @@ -746,7 +746,7 @@ public void testListAllRepositories() throws Exception { GHRepository r = itr.next(); System.out.println(r.getFullName()); assertNotNull(r.getUrl()); - assertNotEquals(0,r.getId()); + assertNotEquals(0L,r.getId()); } } From 587438938ca077dfb4c510376e649c97988d703e Mon Sep 17 00:00:00 2001 From: Trevor Currie Date: Thu, 22 Feb 2018 09:38:25 -0800 Subject: [PATCH 345/390] Added release payload. --- .../org/kohsuke/github/GHEventPayload.java | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHEventPayload.java b/src/main/java/org/kohsuke/github/GHEventPayload.java index b01b32e432..6c72764f4b 100644 --- a/src/main/java/org/kohsuke/github/GHEventPayload.java +++ b/src/main/java/org/kohsuke/github/GHEventPayload.java @@ -716,6 +716,48 @@ public List getModified() { } } + /** + * A release was added to the repo + * + * @see authoritative source + */ + @SuppressFBWarnings(value = {"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR", "NP_UNWRITTEN_FIELD" }, + justification = "Constructed by JSON deserialization") + public static class Release extends GHEventPayload { + private String action; + private GHRelease release; + private GHRepository repository; + + @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Comes from JSON deserialization") + public String getAction() { + return action; + } + + public GHRelease getRelease() { + return release; + } + + public void setRelease(GHRelease release) { + this.release = release; + } + + public GHRepository getRepository() { + return repository; + } + + public void setRepository(GHRepository repository) { + this.repository = repository; + } + + @Override + void wrapUp(GitHub root) { + super.wrapUp(root); + if (repository != null) { + repository.wrap(root); + } + } + } + /** * A repository was created, deleted, made public, or made private. * From f0f6a9988fcf584137f6c9acfedf31ef1f965b9d Mon Sep 17 00:00:00 2001 From: Naadir Jeewa Date: Wed, 28 Feb 2018 00:54:40 +0000 Subject: [PATCH 346/390] OkHttpConnector: Enforce use of TLSv1.2 to match current Github and Github Enterprise TLS support. --- .../github/extras/OkHttpConnector.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/main/java/org/kohsuke/github/extras/OkHttpConnector.java b/src/main/java/org/kohsuke/github/extras/OkHttpConnector.java index faa06b0d3b..e7802c6bae 100644 --- a/src/main/java/org/kohsuke/github/extras/OkHttpConnector.java +++ b/src/main/java/org/kohsuke/github/extras/OkHttpConnector.java @@ -1,13 +1,25 @@ package org.kohsuke.github.extras; +import com.squareup.okhttp.ConnectionSpec; import com.squareup.okhttp.OkHttpClient; import com.squareup.okhttp.OkUrlFactory; + import org.kohsuke.github.HttpConnector; import java.io.IOException; + import java.net.HttpURLConnection; import java.net.URL; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; + +import java.util.Arrays; +import java.util.List; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; + /** * {@link HttpConnector} for {@link OkHttpClient}. * @@ -23,10 +35,33 @@ public class OkHttpConnector implements HttpConnector { private final OkUrlFactory urlFactory; public OkHttpConnector(OkUrlFactory urlFactory) { + urlFactory.client().setSslSocketFactory(TlsSocketFactory()); + urlFactory.client().setConnectionSpecs(TlsConnectionSpecs()); this.urlFactory = urlFactory; } public HttpURLConnection connect(URL url) throws IOException { return urlFactory.open(url); } + + /** Returns TLSv1.2 only SSL Socket Factory. */ + private SSLSocketFactory TlsSocketFactory() { + SSLContext sc; + try { + sc = SSLContext.getInstance("TLSv1.2"); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e.getMessage(), e); + } + try { + sc.init(null, null, null); + return sc.getSocketFactory(); + } catch (KeyManagementException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + /** Returns connection spec with TLS v1.2 in it */ + private List TlsConnectionSpecs() { + return Arrays.asList(ConnectionSpec.MODERN_TLS, ConnectionSpec.CLEARTEXT); + } } From 9cc400a0812036c46e7555c6e95f8bc5dbf7b8bf Mon Sep 17 00:00:00 2001 From: Gyuri Grell Date: Thu, 1 Mar 2018 20:50:00 -0500 Subject: [PATCH 347/390] Fixes #421 - Enum case doesn't match for Pull Request Reviews * Set Jackson to ignore case differences in enums. --- src/main/java/org/kohsuke/github/GitHub.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index f7e0d58096..52a16906da 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -24,6 +24,7 @@ package org.kohsuke.github; import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.introspect.VisibilityChecker.Std; import com.infradna.tool.bridge_method_injector.WithBridgeMethods; @@ -909,6 +910,7 @@ public Reader renderMarkdown(String text) throws IOException { static { MAPPER.setVisibilityChecker(new Std(NONE, NONE, NONE, NONE, ANY)); MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + MAPPER.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS, true); } /* package */ static final String GITHUB_URL = "https://api.github.com"; From 1b04d471b3253fe6eeb7bb66e5bc58d1e516c027 Mon Sep 17 00:00:00 2001 From: itepikin Date: Thu, 22 Mar 2018 11:16:09 +0300 Subject: [PATCH 348/390] Added support for previous_filename for file details in PR. --- .../java/org/kohsuke/github/GHPullRequestFileDetail.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHPullRequestFileDetail.java b/src/main/java/org/kohsuke/github/GHPullRequestFileDetail.java index 1ee55d37cc..35bb86c444 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequestFileDetail.java +++ b/src/main/java/org/kohsuke/github/GHPullRequestFileDetail.java @@ -43,6 +43,7 @@ public class GHPullRequestFileDetail { String raw_url; String contents_url; String patch; + String previous_filename; public String getSha() { return sha; @@ -83,4 +84,9 @@ public URL getContentsUrl() { public String getPatch() { return patch; } + + public String getPreviousFilename() + { + return previous_filename; + } } From a24ac37dfde0c9dc4997ad99006535472bb737fa Mon Sep 17 00:00:00 2001 From: Trevor Currie Date: Wed, 28 Mar 2018 23:30:20 -0700 Subject: [PATCH 349/390] Added request reviewers function within GHPullRequest. --- src/main/java/org/kohsuke/github/GHPullRequest.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index b5f02b964c..cd478fab4e 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -41,6 +41,7 @@ public class GHPullRequest extends GHIssue { private static final String COMMENTS_ACTION = "/comments"; + private static final String REQUEST_REVIEWERS = "/requested_reviewers"; private String patch_url, diff_url, issue_url; private GHCommitPointer base; @@ -345,6 +346,12 @@ public GHPullRequestReviewComment createReviewComment(String body, String sha, S .to(getApiRoute() + COMMENTS_ACTION, GHPullRequestReviewComment.class).wrapUp(this); } + public void requestReviewers(List reviewers) { + return new Requester(root).method("POST") + .with("reviewers", toLogins(reviewers)) + .to(getApiRoute() + REQUEST_REVIEWERS) + } + /** * Merge this pull request. * From db8969707d32ccbda75ec9cf361ad8332a1005f6 Mon Sep 17 00:00:00 2001 From: Rechi Date: Fri, 6 Apr 2018 10:00:00 +0200 Subject: [PATCH 350/390] [fix] fetch labels with HTTP GET method --- src/main/java/org/kohsuke/github/GHPullRequest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index b5f02b964c..1d8545f114 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -393,7 +393,7 @@ public enum MergeMethod{ MERGE, SQUASH, REBASE } private void fetchIssue() throws IOException { if (!fetchedIssueDetails) { - new Requester(root).to(getIssuesApiRoute(), this); + new Requester(root).method("GET").to(getIssuesApiRoute(), this); fetchedIssueDetails = true; } } From 86f868b2d420eaf7d4d40123f219c520cd4e56ca Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Tue, 1 May 2018 06:59:03 -0700 Subject: [PATCH 351/390] Fixed compilation errors introduced by 8b38a20c1849606103dd4f676d5c27613df0b7d8 --- pom.xml | 4 ++-- src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java | 2 +- src/main/java/org/kohsuke/github/GHDeployKey.java | 2 +- src/main/java/org/kohsuke/github/GHKey.java | 2 +- src/main/java/org/kohsuke/github/GHObject.java | 4 ++-- src/main/java/org/kohsuke/github/GHPullRequest.java | 4 ++-- src/main/java/org/kohsuke/github/GHRepository.java | 2 +- src/main/java/org/kohsuke/github/GHSearchBuilder.java | 2 +- src/main/java/org/kohsuke/github/Requester.java | 4 ++-- 9 files changed, 13 insertions(+), 13 deletions(-) diff --git a/pom.xml b/pom.xml index eb71304506..5b11e2f88c 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.93-SNAPSHOT + 1.93 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - HEAD + github-api-1.93 diff --git a/src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java b/src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java index 23960528f2..3d29aa80fd 100644 --- a/src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java +++ b/src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java @@ -1,6 +1,6 @@ package org.kohsuke.github; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import java.io.IOException; diff --git a/src/main/java/org/kohsuke/github/GHDeployKey.java b/src/main/java/org/kohsuke/github/GHDeployKey.java index bfa03b2508..04acda8022 100644 --- a/src/main/java/org/kohsuke/github/GHDeployKey.java +++ b/src/main/java/org/kohsuke/github/GHDeployKey.java @@ -1,6 +1,6 @@ package org.kohsuke.github; -import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; import java.io.IOException; diff --git a/src/main/java/org/kohsuke/github/GHKey.java b/src/main/java/org/kohsuke/github/GHKey.java index 63ab7b3ff9..d4c8197dbf 100644 --- a/src/main/java/org/kohsuke/github/GHKey.java +++ b/src/main/java/org/kohsuke/github/GHKey.java @@ -1,7 +1,7 @@ package org.kohsuke.github; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; /** * SSH public key. diff --git a/src/main/java/org/kohsuke/github/GHObject.java b/src/main/java/org/kohsuke/github/GHObject.java index 3b26ed77cc..2bad0891bc 100644 --- a/src/main/java/org/kohsuke/github/GHObject.java +++ b/src/main/java/org/kohsuke/github/GHObject.java @@ -2,8 +2,8 @@ import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import org.apache.commons.lang.builder.ReflectionToStringBuilder; -import org.apache.commons.lang.builder.ToStringStyle; +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; import javax.annotation.CheckForNull; import java.io.IOException; diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index cd478fab4e..6ffcc1926d 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -347,9 +347,9 @@ public GHPullRequestReviewComment createReviewComment(String body, String sha, S } public void requestReviewers(List reviewers) { - return new Requester(root).method("POST") + new Requester(root).method("POST") .with("reviewers", toLogins(reviewers)) - .to(getApiRoute() + REQUEST_REVIEWERS) + .to(getApiRoute() + REQUEST_REVIEWERS); } /** diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index b40f387b7f..3c80c499ff 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -27,7 +27,7 @@ import com.infradna.tool.bridge_method_injector.WithBridgeMethods; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.apache.commons.codec.binary.Base64; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import java.io.FileNotFoundException; import java.io.IOException; diff --git a/src/main/java/org/kohsuke/github/GHSearchBuilder.java b/src/main/java/org/kohsuke/github/GHSearchBuilder.java index 17c2db85b8..44521687f4 100644 --- a/src/main/java/org/kohsuke/github/GHSearchBuilder.java +++ b/src/main/java/org/kohsuke/github/GHSearchBuilder.java @@ -1,6 +1,6 @@ package org.kohsuke.github; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index 899597b33e..c4d62ba625 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -26,7 +26,7 @@ import com.fasterxml.jackson.databind.JsonMappingException; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import javax.annotation.CheckForNull; import javax.annotation.WillClose; @@ -63,7 +63,7 @@ import static java.util.logging.Level.FINE; import static java.util.logging.Level.FINEST; import static java.util.logging.Level.INFO; -import static org.apache.commons.lang.StringUtils.defaultString; +import static org.apache.commons.lang3.StringUtils.defaultString; import static org.kohsuke.github.GitHub.MAPPER; /** From 4dce17363059521f90d9b58eacd4edc434544db5 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Tue, 1 May 2018 07:03:53 -0700 Subject: [PATCH 352/390] Extracted the List->List out to Requester for reuse --- src/main/java/org/kohsuke/github/GHIssue.java | 19 +++++-------------- .../org/kohsuke/github/GHPullRequest.java | 4 ++-- .../java/org/kohsuke/github/Requester.java | 8 ++++++++ 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHIssue.java b/src/main/java/org/kohsuke/github/GHIssue.java index 186ea16719..f7cfd9245c 100644 --- a/src/main/java/org/kohsuke/github/GHIssue.java +++ b/src/main/java/org/kohsuke/github/GHIssue.java @@ -29,7 +29,6 @@ import java.io.IOException; import java.net.URL; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -49,6 +48,8 @@ * @see GHIssueSearchBuilder */ public class GHIssue extends GHObject implements Reactable{ + private static final String ASSIGNEES = "assignees"; + GitHub root; GHRepository owner; @@ -268,8 +269,7 @@ public void addAssignees(GHUser... assignees) throws IOException { } public void addAssignees(Collection assignees) throws IOException { - List names = toLogins(assignees); - root.retrieve().method("POST").with("assignees",names).to(getIssuesApiRoute()+"/assignees",this); + root.retrieve().method("POST").withLogins(ASSIGNEES,assignees).to(getIssuesApiRoute()+"/assignees",this); } public void setAssignees(GHUser... assignees) throws IOException { @@ -277,7 +277,7 @@ public void setAssignees(GHUser... assignees) throws IOException { } public void setAssignees(Collection assignees) throws IOException { - editIssue("assignees",toLogins(assignees)); + new Requester(root).withLogins(ASSIGNEES, assignees).method("PATCH").to(getIssuesApiRoute()); } public void removeAssignees(GHUser... assignees) throws IOException { @@ -285,16 +285,7 @@ public void removeAssignees(GHUser... assignees) throws IOException { } public void removeAssignees(Collection assignees) throws IOException { - List names = toLogins(assignees); - root.retrieve().method("DELETE").with("assignees",names).inBody().to(getIssuesApiRoute()+"/assignees",this); - } - - private List toLogins(Collection assignees) { - List names = new ArrayList(assignees.size()); - for (GHUser a : assignees) { - names.add(a.getLogin()); - } - return names; + root.retrieve().method("DELETE").withLogins(ASSIGNEES,assignees).inBody().to(getIssuesApiRoute()+"/assignees",this); } protected String getApiRoute() { diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index 6ffcc1926d..fb7f8aca19 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -346,9 +346,9 @@ public GHPullRequestReviewComment createReviewComment(String body, String sha, S .to(getApiRoute() + COMMENTS_ACTION, GHPullRequestReviewComment.class).wrapUp(this); } - public void requestReviewers(List reviewers) { + public void requestReviewers(List reviewers) throws IOException { new Requester(root).method("POST") - .with("reviewers", toLogins(reviewers)) + .withLogins("reviewers", reviewers) .to(getApiRoute() + REQUEST_REVIEWERS); } diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index c4d62ba625..4670e311e5 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -169,6 +169,14 @@ public Requester with(String key, Collection value) { return _with(key, value); } + public Requester withLogins(String key, Collection users) { + List names = new ArrayList(users.size()); + for (GHUser a : users) { + names.add(a.getLogin()); + } + return with(key,names); + } + public Requester with(String key, Map value) { return _with(key, value); } From f2ed7c15ced688ec850a3cf055dfce497da47b3d Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Tue, 1 May 2018 07:12:30 -0700 Subject: [PATCH 353/390] Looks like the permission scheme changed on jenkinsci/violations-plugin --- src/test/java/org/kohsuke/github/AppTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/kohsuke/github/AppTest.java b/src/test/java/org/kohsuke/github/AppTest.java index e069a74edb..807e8ca7c6 100755 --- a/src/test/java/org/kohsuke/github/AppTest.java +++ b/src/test/java/org/kohsuke/github/AppTest.java @@ -304,7 +304,7 @@ public void testGetTeamsForRepo() throws Exception { @Test public void testMembership() throws Exception { - Set members = gitHub.getOrganization("jenkinsci").getRepository("violations-plugin").getCollaboratorNames(); + Set members = gitHub.getOrganization("github-api-test-org").getRepository("jenkins").getCollaboratorNames(); System.out.println(members.contains("kohsuke")); } From 7d294ee8c21c1fd59388d96fb0ace615c8bb8d8c Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Tue, 1 May 2018 07:26:09 -0700 Subject: [PATCH 354/390] Looks like release rollback didn't quite complete --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 5b11e2f88c..eb71304506 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.93 + 1.93-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - github-api-1.93 + HEAD From 38b77a9c7948ae335cb5cb09a861d0451d9b81c0 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Tue, 1 May 2018 07:56:27 -0700 Subject: [PATCH 355/390] [maven-release-plugin] prepare release github-api-1.93 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index eb71304506..5b11e2f88c 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.93-SNAPSHOT + 1.93 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - HEAD + github-api-1.93 From d61697a152c4ca50e82a95c0bee04b61430ac358 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Tue, 1 May 2018 07:56:38 -0700 Subject: [PATCH 356/390] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 5b11e2f88c..3f134bed94 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.93 + 1.94-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - github-api-1.93 + HEAD From 1145941d11b03dabfea98a4cb0cff64e688df309 Mon Sep 17 00:00:00 2001 From: Jae Gangemi Date: Sun, 27 May 2018 15:33:58 -0600 Subject: [PATCH 357/390] - add support for signed commits - add support for required number of reviews --- .../java/org/kohsuke/github/GHBranch.java | 4 +- .../kohsuke/github/GHBranchProtection.java | 58 +++++++++++++++++++ .../github/GHBranchProtectionBuilder.java | 34 ++++++++--- .../java/org/kohsuke/github/Previews.java | 2 + .../github/GHBranchProtectionTest.java | 27 +++++++++ 5 files changed, 114 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHBranch.java b/src/main/java/org/kohsuke/github/GHBranch.java index 1ce9c29ac4..dbedcb64aa 100644 --- a/src/main/java/org/kohsuke/github/GHBranch.java +++ b/src/main/java/org/kohsuke/github/GHBranch.java @@ -67,7 +67,7 @@ public URL getProtectionUrl() { @Preview @Deprecated public GHBranchProtection getProtection() throws IOException { - return root.retrieve().withPreview(LOKI).to(protection_url, GHBranchProtection.class); + return root.retrieve().withPreview(LOKI).to(protection_url, GHBranchProtection.class).wrap(this); } /** @@ -82,7 +82,7 @@ public String getSHA1() { */ @Preview @Deprecated public void disableProtection() throws IOException { - new Requester(root).method("DELETE").withPreview(LOKI).to(protection_url); + new Requester(root).method("DELETE").to(protection_url); } /** diff --git a/src/main/java/org/kohsuke/github/GHBranchProtection.java b/src/main/java/org/kohsuke/github/GHBranchProtection.java index 7e43bd69cb..a73d5ae2c4 100644 --- a/src/main/java/org/kohsuke/github/GHBranchProtection.java +++ b/src/main/java/org/kohsuke/github/GHBranchProtection.java @@ -3,14 +3,21 @@ import com.fasterxml.jackson.annotation.JsonProperty; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import static org.kohsuke.github.Previews.ZZZAX; + +import java.io.IOException; import java.util.Collection; @SuppressFBWarnings(value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD", "URF_UNREAD_FIELD" }, justification = "JSON API") public class GHBranchProtection { + private static final String REQUIRE_SIGNATURES_URI = "/required_signatures"; + @JsonProperty("enforce_admins") private EnforceAdmins enforceAdmins; + private GitHub root; + @JsonProperty("required_pull_request_reviews") private RequiredReviews requiredReviews; @@ -23,6 +30,18 @@ public class GHBranchProtection { @JsonProperty private String url; + @Preview @Deprecated + public RequiredSignatures enabledSignedCommits() throws IOException { + return requester().method("POST") + .to(url + REQUIRE_SIGNATURES_URI, RequiredSignatures.class); + } + + @Preview @Deprecated + public void disableSignedCommits() throws IOException { + requester().method("DELETE") + .to(url + REQUIRE_SIGNATURES_URI); + } + public EnforceAdmins getEnforceAdmins() { return enforceAdmins; } @@ -31,6 +50,12 @@ public RequiredReviews getRequiredReviews() { return requiredReviews; } + @Preview @Deprecated + public RequiredSignatures getRequiredSignatures() throws IOException { + return requester().method("GET") + .to(url + REQUIRE_SIGNATURES_URI, RequiredSignatures.class); + } + public RequiredStatusChecks getRequiredStatusChecks() { return requiredStatusChecks; } @@ -43,6 +68,15 @@ public String getUrl() { return url; } + GHBranchProtection wrap(GHBranch branch) { + this.root = branch.getRoot(); + return this; + } + + private Requester requester() { + return new Requester(root).withPreview(ZZZAX); + } + public static class EnforceAdmins { @JsonProperty private boolean enabled; @@ -69,6 +103,9 @@ public static class RequiredReviews { @JsonProperty("require_code_owner_reviews") private boolean requireCodeOwnerReviews; + @JsonProperty("required_approving_review_count") + private int requiredReviewers; + @JsonProperty private String url; @@ -87,6 +124,27 @@ public boolean isDismissStaleReviews() { public boolean isRequireCodeOwnerReviews() { return requireCodeOwnerReviews; } + + public int getRequiredReviewers() + { + return requiredReviewers; + } + } + + public static class RequiredSignatures { + @JsonProperty + private boolean enabled; + + @JsonProperty + private String url; + + public String getUrl() { + return url; + } + + public boolean isEnabled() { + return enabled; + } } public static class RequiredStatusChecks { diff --git a/src/main/java/org/kohsuke/github/GHBranchProtectionBuilder.java b/src/main/java/org/kohsuke/github/GHBranchProtectionBuilder.java index dc7dbd8845..61e9b70fea 100644 --- a/src/main/java/org/kohsuke/github/GHBranchProtectionBuilder.java +++ b/src/main/java/org/kohsuke/github/GHBranchProtectionBuilder.java @@ -44,7 +44,12 @@ public GHBranchProtectionBuilder addRequiredChecks(String... checks) { } public GHBranchProtectionBuilder dismissStaleReviews() { - getPrReviews().put("dismiss_stale_reviews", true); + dismissStaleReviews(true); + return this; + } + + public GHBranchProtectionBuilder dismissStaleReviews(boolean v) { + getPrReviews().put("dismiss_stale_reviews", v); return this; } @@ -54,7 +59,8 @@ public GHBranchProtection enable() throws IOException { .withNullable("required_pull_request_reviews", prReviews) .withNullable("restrictions", restrictions) .withNullable("enforce_admins", enforceAdmins) - .to(branch.getProtectionUrl().toString(), GHBranchProtection.class); + .to(branch.getProtectionUrl().toString(), GHBranchProtection.class) + .wrap(branch); } public GHBranchProtectionBuilder includeAdmins() { @@ -66,6 +72,11 @@ public GHBranchProtectionBuilder includeAdmins(boolean v) { return this; } + public GHBranchProtectionBuilder requiredReviewers(int v) { + getPrReviews().put("required_approving_review_count", v); + return this; + } + public GHBranchProtectionBuilder requireBranchIsUpToDate() { return requireBranchIsUpToDate(true); } @@ -89,6 +100,16 @@ public GHBranchProtectionBuilder requireReviews() { return this; } + public GHBranchProtectionBuilder restrictReviewDismissals() { + getPrReviews(); + + if (!prReviews.containsKey("dismissal_restrictions")) { + prReviews.put("dismissal_restrictions", new Restrictions()); + } + + return this; + } + public GHBranchProtectionBuilder restrictPushAccess() { getRestrictions(); return this; @@ -151,12 +172,7 @@ public GHBranchProtectionBuilder userReviewDismissals(GHUser... users) { } private void addReviewRestriction(String restriction, boolean isTeam) { - getPrReviews(); - - if (!prReviews.containsKey("dismissal_restrictions")) { - prReviews.put("dismissal_restrictions", new Restrictions()); - } - + restrictReviewDismissals(); Restrictions restrictions = (Restrictions) prReviews.get("dismissal_restrictions"); if (isTeam) { @@ -188,7 +204,7 @@ private StatusChecks getStatusChecks() { } private Requester requester() { - return new Requester(branch.getRoot()).withPreview(LOKI); + return new Requester(branch.getRoot()).withPreview(LUKE_CAGE); } private static class Restrictions { diff --git a/src/main/java/org/kohsuke/github/Previews.java b/src/main/java/org/kohsuke/github/Previews.java index 3f98c3d4b9..f1686e24aa 100644 --- a/src/main/java/org/kohsuke/github/Previews.java +++ b/src/main/java/org/kohsuke/github/Previews.java @@ -5,7 +5,9 @@ */ /*package*/ class Previews { static final String LOKI = "application/vnd.github.loki-preview+json"; + static final String LUKE_CAGE = "application/vnd.github.luke-cage-preview+json"; static final String DRAX = "application/vnd.github.drax-preview+json"; static final String SQUIRREL_GIRL = "application/vnd.github.squirrel-girl-preview"; static final String CLOAK = "application/vnd.github.cloak-preview"; + static final String ZZZAX = "application/vnd.github.zzzax-preview+json"; } diff --git a/src/test/java/org/kohsuke/github/GHBranchProtectionTest.java b/src/test/java/org/kohsuke/github/GHBranchProtectionTest.java index b7ae713d87..a6b711b6c0 100644 --- a/src/test/java/org/kohsuke/github/GHBranchProtectionTest.java +++ b/src/test/java/org/kohsuke/github/GHBranchProtectionTest.java @@ -4,6 +4,7 @@ import org.junit.Test; import org.kohsuke.github.GHBranchProtection.EnforceAdmins; import org.kohsuke.github.GHBranchProtection.RequiredReviews; +import org.kohsuke.github.GHBranchProtection.RequiredSignatures; import org.kohsuke.github.GHBranchProtection.RequiredStatusChecks; import java.io.FileNotFoundException; @@ -32,6 +33,12 @@ public void setUp() throws Exception { branch = repo.getBranch(BRANCH); if (branch.isProtected()) { + GHBranchProtection protection = branch.getProtection(); + if (protection.getRequiredSignatures().isEnabled()) { + protection.disableSignedCommits(); + } + + assertFalse(protection.getRequiredSignatures().isEnabled()); branch.disableProtection(); } @@ -47,6 +54,7 @@ public void testEnableBranchProtections() throws Exception { .requireBranchIsUpToDate() .requireCodeOwnReviews() .dismissStaleReviews() + .requiredReviewers(2) .includeAdmins() .enable(); @@ -59,6 +67,7 @@ public void testEnableBranchProtections() throws Exception { assertNotNull(requiredReviews); assertTrue(requiredReviews.isDismissStaleReviews()); assertTrue(requiredReviews.isRequireCodeOwnerReviews()); + assertEquals(2, requiredReviews.getRequiredReviewers()); EnforceAdmins enforceAdmins = protection.getEnforceAdmins(); assertNotNull(enforceAdmins); @@ -79,4 +88,22 @@ public void testEnableRequireReviewsOnly() throws Exception { assertNotNull(protection.getRequiredReviews()); } + + @Test + public void testSignedCommits() throws Exception { + GHBranchProtection protection = branch.enableProtection().enable(); + + RequiredSignatures signatures = protection.getRequiredSignatures(); + assertNotNull(signatures); + assertFalse(signatures.isEnabled()); + + signatures = protection.enabledSignedCommits(); + assertNotNull(signatures); + assertTrue(signatures.isEnabled()); + + protection.disableSignedCommits(); + signatures = protection.getRequiredSignatures(); + assertNotNull(signatures); + assertFalse(signatures.isEnabled()); + } } From ca6d77cbb33893b3f6b7827a7966add69c45ea58 Mon Sep 17 00:00:00 2001 From: Jae Gangemi Date: Mon, 28 May 2018 17:49:21 -0600 Subject: [PATCH 358/390] - remove unthrown IOException --- src/main/java/org/kohsuke/github/GHOrganization.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHOrganization.java b/src/main/java/org/kohsuke/github/GHOrganization.java index f174decf2f..3bf34e2c98 100644 --- a/src/main/java/org/kohsuke/github/GHOrganization.java +++ b/src/main/java/org/kohsuke/github/GHOrganization.java @@ -50,7 +50,7 @@ public GHRepository createRepository(String name, String description, String hom * You use the returned builder to set various properties, then call {@link GHCreateRepositoryBuilder#create()} * to finally createa repository. */ - public GHCreateRepositoryBuilder createRepository(String name) throws IOException { + public GHCreateRepositoryBuilder createRepository(String name) { return new GHCreateRepositoryBuilder(root,"/orgs/"+login+"/repos",name); } From fe5ea52cdf9d2af3b434ac28428fab78270d7bdd Mon Sep 17 00:00:00 2001 From: Rechi Date: Tue, 29 May 2018 22:00:00 +0200 Subject: [PATCH 359/390] [feature] implement Repository Invitations API fixes #374 --- .../java/org/kohsuke/github/GHInvitation.java | 45 +++++++++++++++++++ .../java/org/kohsuke/github/GHRepository.java | 16 +++++++ src/main/java/org/kohsuke/github/GitHub.java | 9 ++++ 3 files changed, 70 insertions(+) create mode 100644 src/main/java/org/kohsuke/github/GHInvitation.java diff --git a/src/main/java/org/kohsuke/github/GHInvitation.java b/src/main/java/org/kohsuke/github/GHInvitation.java new file mode 100644 index 0000000000..6c285fefd1 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHInvitation.java @@ -0,0 +1,45 @@ +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.Map; +import java.util.TreeMap; + +public class GHInvitation extends GHObject { + /*package almost final*/ GitHub root; + + private int id; + private GHRepository repository; + private GHUser invitee, inviter; + private String permissions; + private String html_url; + + /*package*/ GHInvitation wrapUp(GitHub root) { + this.root = root; + return this; + } + + /** + * Accept a repository invitation. + */ + public void accept() throws IOException { + root.retrieve().method("PATCH").to("/user/repository_invitations/" + id); + } + + /** + * Decline a repository invitation. + */ + public void decline() throws IOException { + root.retrieve().method("DELETE").to("/user/repository_invitations/" + id); + } + + @Override + public URL getHtmlUrl() { + return GitHub.parseURL(html_url); + } +} diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 3c80c499ff..d72cba14d3 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -1137,6 +1137,22 @@ public GHLabel createLabel(String name, String color) throws IOException { .to(getApiTailUrl("labels"), GHLabel.class).wrapUp(this); } + /** + * Lists all the invitations. + */ + public PagedIterable listInvitations() { + return new PagedIterable() { + public PagedIterator _iterator(int pageSize) { + return new PagedIterator(root.retrieve().asIterator(String.format("/repos/%s/%s/invitations", getOwnerName(), name), GHInvitation[].class, pageSize)) { + protected void wrapUp(GHInvitation[] page) { + for (GHInvitation c : page) + c.wrapUp(root); + } + }; + } + }; + } + /** * Lists all the subscribers (aka watchers.) * diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 52a16906da..d5d0a2be33 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -530,6 +530,15 @@ public GHLicense getLicense(String key) throws IOException { } /** + * Gets complete list of open invitations for current user. + */ + public List getMyInvitations() throws IOException { + GHInvitation[] invitations = retrieve().to("/user/repository_invitations", GHInvitation[].class); + for (GHInvitation i : invitations) { + i.wrapUp(this); + } + return Arrays.asList(invitations); + } /** * This method returns a shallowly populated organizations. From eacdd7afe8cf25c9cd0e4ba97f914cd6e9a45800 Mon Sep 17 00:00:00 2001 From: Jae Gangemi Date: Wed, 30 May 2018 08:18:25 -0600 Subject: [PATCH 360/390] - added overloaded 'uploadAsset' method --- src/main/java/org/kohsuke/github/GHRelease.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHRelease.java b/src/main/java/org/kohsuke/github/GHRelease.java index a299add2c5..d49c0a2890 100644 --- a/src/main/java/org/kohsuke/github/GHRelease.java +++ b/src/main/java/org/kohsuke/github/GHRelease.java @@ -3,6 +3,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStream; import java.net.URL; import java.util.Arrays; import java.util.Date; @@ -125,12 +126,16 @@ static GHRelease[] wrap(GHRelease[] releases, GHRepository owner) { * handling of the HTTP requests to github's API. */ public GHAsset uploadAsset(File file, String contentType) throws IOException { + return uploadAsset(file.getName(), new FileInputStream(file), contentType); + } + + public GHAsset uploadAsset(String filename, InputStream stream, String contentType) throws IOException { Requester builder = new Requester(owner.root); String url = format("https://uploads.github.com%s/releases/%d/assets?name=%s", - owner.getApiTailUrl(""), getId(), file.getName()); + owner.getApiTailUrl(""), getId(), filename); return builder.contentType(contentType) - .with(new FileInputStream(file)) + .with(stream) .to(url, GHAsset.class).wrap(this); } From fd37a2c46605ff02cccf31731cc668037c66e7e4 Mon Sep 17 00:00:00 2001 From: l3ender Date: Wed, 6 Jun 2018 11:44:46 -0500 Subject: [PATCH 361/390] Add support for repository searching by "topic" See https://help.github.com/articles/searching-repositories/#search-by-topic --- .../java/org/kohsuke/github/GHRepositorySearchBuilder.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHRepositorySearchBuilder.java b/src/main/java/org/kohsuke/github/GHRepositorySearchBuilder.java index 642f7f3d95..0ecd77e600 100644 --- a/src/main/java/org/kohsuke/github/GHRepositorySearchBuilder.java +++ b/src/main/java/org/kohsuke/github/GHRepositorySearchBuilder.java @@ -55,6 +55,10 @@ public GHRepositorySearchBuilder stars(String v) { return q("stars:"+v); } + public GHRepositorySearchBuilder topic(String v) { + return q("topic:"+v); + } + public GHRepositorySearchBuilder order(GHDirection v) { req.with("order",v); return this; From 943f47d29d86689fda92446e3f64527468d40af1 Mon Sep 17 00:00:00 2001 From: Oliver Noguera Date: Thu, 15 Mar 2018 18:39:32 +0100 Subject: [PATCH 362/390] Add sha1 to updateFiles see https://developer.github.com/v3/repos/contents/#update-a-file --- .../java/org/kohsuke/github/GHRepository.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 3c80c499ff..869d11c54f 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -1394,27 +1394,29 @@ public GHContent getReadme() throws IOException { return requester.to(getApiTailUrl("readme"), GHContent.class).wrap(this); } - public GHContentUpdateResponse createContent(String content, String commitMessage, String path) throws IOException { - return createContent(content, commitMessage, path, null); + public GHContentUpdateResponse createContent(String content, String commitMessage, String path,String sha1) throws IOException { + return createContent(content, commitMessage, path, null,sha1); } - public GHContentUpdateResponse createContent(String content, String commitMessage, String path, String branch) throws IOException { + public GHContentUpdateResponse createContent(String content, String commitMessage, String path, String branch, String sha1) throws IOException { final byte[] payload; try { payload = content.getBytes("UTF-8"); } catch (UnsupportedEncodingException ex) { throw (IOException) new IOException("UTF-8 encoding is not supported").initCause(ex); } - return createContent(payload, commitMessage, path, branch); + return createContent(payload, commitMessage, path, branch,sha1); } - public GHContentUpdateResponse createContent(byte[] contentBytes, String commitMessage, String path) throws IOException { - return createContent(contentBytes, commitMessage, path, null); + public GHContentUpdateResponse createContent(byte[] contentBytes, String commitMessage, String path,String sha1) throws IOException { + return createContent(contentBytes, commitMessage, path, null,sha1); } - public GHContentUpdateResponse createContent(byte[] contentBytes, String commitMessage, String path, String branch) throws IOException { + public GHContentUpdateResponse createContent(byte[] contentBytes, String commitMessage, String path, String branch, + String sha1) throws IOException { Requester requester = new Requester(root) .with("path", path) + .with("sha", sha1) .with("message", commitMessage) .with("content", Base64.encodeBase64String(contentBytes)) .method("PUT"); From f68a85056ed52b26eb9c09207649c34a5a1fffb4 Mon Sep 17 00:00:00 2001 From: onoguera-ob Date: Thu, 15 Mar 2018 18:57:41 +0100 Subject: [PATCH 363/390] Update integration test. --- .../java/org/kohsuke/github/GHContentIntegrationTest.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test/java/org/kohsuke/github/GHContentIntegrationTest.java b/src/test/java/org/kohsuke/github/GHContentIntegrationTest.java index 8e3873708b..b1ab9387f7 100644 --- a/src/test/java/org/kohsuke/github/GHContentIntegrationTest.java +++ b/src/test/java/org/kohsuke/github/GHContentIntegrationTest.java @@ -53,7 +53,10 @@ public void testGetDirectoryContentTrailingSlash() throws Exception { @Test public void testCRUDContent() throws Exception { - GHContentUpdateResponse created = repo.createContent("this is an awesome file I created\n", "Creating a file for integration tests.", createdFilename); + ; + GHContentUpdateResponse created = + repo.createContent("this is an awesome file I created\n", "Creating a file for integration tests.", createdFilename, + repo.getFileContent(createdFilename).getSha()); GHContent createdContent = created.getContent(); assertNotNull(created.getCommit()); From 2fcfb2f67df5075989d46c8a37daa6601321e06e Mon Sep 17 00:00:00 2001 From: Sharath Date: Tue, 12 Jun 2018 18:20:47 -0700 Subject: [PATCH 364/390] address review comments in supporting updating content with sha --- .../github/GHContentUpdateRequest.java | 97 +++++++++++++++++++ .../java/org/kohsuke/github/GHRepository.java | 53 +++++++--- .../org/kohsuke/github/PullRequestTest.java | 23 +++++ 3 files changed, 160 insertions(+), 13 deletions(-) create mode 100644 src/main/java/org/kohsuke/github/GHContentUpdateRequest.java diff --git a/src/main/java/org/kohsuke/github/GHContentUpdateRequest.java b/src/main/java/org/kohsuke/github/GHContentUpdateRequest.java new file mode 100644 index 0000000000..80bd0f6aa2 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHContentUpdateRequest.java @@ -0,0 +1,97 @@ +package org.kohsuke.github; + +public class GHContentUpdateRequest { + private final String path; + private final String branch; + private final String sha; + private final byte[] content; + private final String commitMessage; + + public static GHContentUpdateRequest.Builder getBuilder() { + return new GHContentUpdateRequest.Builder(); + } + + public GHContentUpdateRequest(String path, String branch, String sha, byte[] content, String commitMessage) { + this.path = path; + this.branch = branch; + this.sha = sha; + this.content = content; + this.commitMessage = commitMessage; + } + + private GHContentUpdateRequest(Builder builder) { + this.path = builder.path; + this.branch = builder.branch; + this.sha = builder.sha; + this.content = builder.content; + this.commitMessage = builder.commitMessage; + } + + public static Builder newGHContentUpdateRequest() { + return new Builder(); + } + + public String getPath() { + return path; + } + + public String getBranch() { + return branch; + } + + public String getSha() { + return sha; + } + + public byte[] getContent() { + return content; + } + + public String getCommitMessage() { + return commitMessage; + } + + public static final class Builder { + private String path; + private String branch; + private String sha; + private byte[] content; + private String commitMessage; + + private Builder() { + } + + public GHContentUpdateRequest build() { + return new GHContentUpdateRequest(this); + } + + public Builder path(String path) { + this.path = path; + return this; + } + + public Builder branch(String branch) { + this.branch = branch; + return this; + } + + public Builder sha(String sha) { + this.sha = sha; + return this; + } + + public Builder content(byte[] content) { + this.content = content; + return this; + } + public Builder content(String content) { + this.content = content.getBytes(); + return this; + } + + public Builder commitMessage(String commitMessage) { + this.commitMessage = commitMessage; + return this; + } + } +} diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 869d11c54f..302903ae8d 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -1394,32 +1394,59 @@ public GHContent getReadme() throws IOException { return requester.to(getApiTailUrl("readme"), GHContent.class).wrap(this); } - public GHContentUpdateResponse createContent(String content, String commitMessage, String path,String sha1) throws IOException { - return createContent(content, commitMessage, path, null,sha1); + public GHContentUpdateResponse createContent(GHContentUpdateRequest updateRequest) throws IOException { + return createContent(updateRequest.getContent(), updateRequest.getCommitMessage(), updateRequest.getPath(), updateRequest.getBranch(), updateRequest.getSha()); } - public GHContentUpdateResponse createContent(String content, String commitMessage, String path, String branch, String sha1) throws IOException { + /** + * Use {@link GHContentUpdateRequest}. + */ + @Deprecated + public GHContentUpdateResponse createContent(String content, String commitMessage, String path) throws IOException { + return createContent(content.getBytes(), commitMessage, path, null, null); + } + + /** + * Use {@link GHContentUpdateRequest}. + */ + @Deprecated + public GHContentUpdateResponse createContent(String content, String commitMessage, String path, String branch) throws IOException { final byte[] payload; try { payload = content.getBytes("UTF-8"); } catch (UnsupportedEncodingException ex) { throw (IOException) new IOException("UTF-8 encoding is not supported").initCause(ex); } - return createContent(payload, commitMessage, path, branch,sha1); + return createContent(payload, commitMessage, path, branch, null); } - public GHContentUpdateResponse createContent(byte[] contentBytes, String commitMessage, String path,String sha1) throws IOException { - return createContent(contentBytes, commitMessage, path, null,sha1); + /** + * Use {@link GHContentUpdateRequest}. + */ + @Deprecated + public GHContentUpdateResponse createContent(byte[] contentBytes, String commitMessage, String path) throws IOException { + return createContent(contentBytes, commitMessage, path, null, null); } - public GHContentUpdateResponse createContent(byte[] contentBytes, String commitMessage, String path, String branch, - String sha1) throws IOException { + /** + * Use {@link GHContentUpdateRequest}. + */ + @Deprecated + public GHContentUpdateResponse createContent(byte[] contentBytes, String commitMessage, String path, String branch) throws IOException { + return createContent(contentBytes, commitMessage, path, branch, null); + } + + private GHContentUpdateResponse createContent(byte[] contentBytes, String commitMessage, String path, String branch, String sha1) throws IOException { Requester requester = new Requester(root) - .with("path", path) - .with("sha", sha1) - .with("message", commitMessage) - .with("content", Base64.encodeBase64String(contentBytes)) - .method("PUT"); + .with("path", path) + .with("message", commitMessage) + .with("content", Base64.encodeBase64String(contentBytes)) + .method("PUT"); + + if (sha1 != null) { + requester.with("sha", sha1); + } + if (branch != null) { requester.with("branch", branch); diff --git a/src/test/java/org/kohsuke/github/PullRequestTest.java b/src/test/java/org/kohsuke/github/PullRequestTest.java index c2a6a2705e..8bbada55bf 100644 --- a/src/test/java/org/kohsuke/github/PullRequestTest.java +++ b/src/test/java/org/kohsuke/github/PullRequestTest.java @@ -105,6 +105,7 @@ public void testSquashMerge() throws Exception { String name = rnd.next(); GHRef masterRef = getRepository().getRef("heads/master"); GHRef branchRef = getRepository().createRef("refs/heads/" + name, masterRef.getObject().getSha()); + getRepository().createContent(name, name, name, name); Thread.sleep(1000); GHPullRequest p = getRepository().createPullRequest(name, name, "master", "## test squash"); @@ -112,6 +113,28 @@ public void testSquashMerge() throws Exception { p.merge("squash merge", null, GHPullRequest.MergeMethod.SQUASH); branchRef.delete(); } + @Test + public void testUpdateContentSquashMerge() throws Exception { + String name = rnd.next(); + GHRef masterRef = getRepository().getRef("heads/master"); + GHRef branchRef = getRepository().createRef("refs/heads/" + name, masterRef.getObject().getSha()); + + GHContentUpdateResponse response = getRepository().createContent(name, name, name, name); + Thread.sleep(1000); + + GHContentUpdateRequest updateRequest = GHContentUpdateRequest.getBuilder() + .content(name + name) + .path(name) + .branch(name) + .commitMessage(name) + .sha(response.getContent().getSha()) + .build(); + getRepository().createContent(updateRequest); + GHPullRequest p = getRepository().createPullRequest(name, name, "master", "## test squash"); + Thread.sleep(1000); + p.merge("squash merge", null, GHPullRequest.MergeMethod.SQUASH); + branchRef.delete(); + } @Test // Requires push access to the test repo to pass From e368a17420e8c7e29f154d6558755cdfe977b5b7 Mon Sep 17 00:00:00 2001 From: Werner <1331699+Arrow768@users.noreply.github.com> Date: Sun, 1 Jul 2018 12:23:13 +0200 Subject: [PATCH 365/390] Adds the GHEventPayload.Issue class --- .../org/kohsuke/github/GHEventPayload.java | 45 +++++++++++++++++++ .../kohsuke/github/GHEventPayloadTest.java | 16 +++++-- 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHEventPayload.java b/src/main/java/org/kohsuke/github/GHEventPayload.java index b01b32e432..28c33b940c 100644 --- a/src/main/java/org/kohsuke/github/GHEventPayload.java +++ b/src/main/java/org/kohsuke/github/GHEventPayload.java @@ -174,6 +174,51 @@ void wrapUp(GitHub root) { } } + /** + * A Issue has been assigned, unassigned, labeled, unlabeled, opened, edited, milestoned, demilestoned, closed, or reopened. + * + * @see authoritative source + */ + @SuppressFBWarnings(value = {"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR", "NP_UNWRITTEN_FIELD" }, + justification = "Constructed by JSON deserialization") + public static class Issue extends GHEventPayload { + private String action; + private GHIssue issue; + private GHRepository repository; + + @SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Comes from JSON deserialization") + public String getAction() { + return action; + } + + public GHIssue getIssue() { + return issue; + } + + public void setIssue(GHIssue issue) { + this.issue = issue; + } + + public GHRepository getRepository() { + return repository; + } + + public void setRepository(GHRepository repository) { + this.repository = repository; + } + + @Override + void wrapUp(GitHub root) { + super.wrapUp(root); + if (repository != null) { + repository.wrap(root); + issue.wrap(repository); + } else { + issue.wrap(root); + } + } + } + /** * A comment was added to an issue * diff --git a/src/test/java/org/kohsuke/github/GHEventPayloadTest.java b/src/test/java/org/kohsuke/github/GHEventPayloadTest.java index 71f9fd3e68..b0c2a05408 100644 --- a/src/test/java/org/kohsuke/github/GHEventPayloadTest.java +++ b/src/test/java/org/kohsuke/github/GHEventPayloadTest.java @@ -120,9 +120,19 @@ public void issue_comment() throws Exception { assertThat(event.getSender().getLogin(), is("baxterthehacker")); } -// TODO implement support classes and write test -// @Test -// public void issues() throws Exception {} + @Test + public void issues() throws Exception { + GHEventPayload.Issue event = GitHub.offline().parseEventPayload(payload.asReader(),GHEventPayload.Issue.class); + assertThat(event.getAction(),is("opened")); + assertThat(event.getIssue().getNumber(), is(2)); + assertThat(event.getIssue().getTitle(), is("Spelling error in the README file")); + assertThat(event.getIssue().getState(), is(GHIssueState.OPEN)); + assertThat(event.getIssue().getLabels().size(), is(1)); + assertThat(event.getIssue().getLabels().iterator().next().getName(), is("bug")); + assertThat(event.getRepository().getName(), is("public-repo")); + assertThat(event.getRepository().getOwner().getLogin(), is("baxterthehacker")); + assertThat(event.getSender().getLogin(), is("baxterthehacker")); + } // TODO implement support classes and write test // @Test From 0ffcbdbd38c786994029d0d0f93870da3ad12b15 Mon Sep 17 00:00:00 2001 From: Daniel Beck Date: Tue, 17 Jul 2018 11:27:54 +0200 Subject: [PATCH 366/390] Fix pagination for APIs that supported it ad hoc --- src/main/java/org/kohsuke/github/GHOrganization.java | 4 ++-- src/main/java/org/kohsuke/github/GHPerson.java | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHOrganization.java b/src/main/java/org/kohsuke/github/GHOrganization.java index f174decf2f..d05e441223 100644 --- a/src/main/java/org/kohsuke/github/GHOrganization.java +++ b/src/main/java/org/kohsuke/github/GHOrganization.java @@ -269,7 +269,7 @@ protected void wrapUp(GHEventInfo[] page) { public PagedIterable listRepositories(final int pageSize) { return new PagedIterable() { public PagedIterator _iterator(int pageSize) { - return new PagedIterator(root.retrieve().asIterator("/orgs/" + login + "/repos?per_page=" + pageSize, GHRepository[].class, pageSize)) { + return new PagedIterator(root.retrieve().asIterator("/orgs/" + login + "/repos", GHRepository[].class, pageSize)) { @Override protected void wrapUp(GHRepository[] page) { for (GHRepository c : page) @@ -277,7 +277,7 @@ protected void wrapUp(GHRepository[] page) { } }; } - }; + }.withPageSize(pageSize); } /** diff --git a/src/main/java/org/kohsuke/github/GHPerson.java b/src/main/java/org/kohsuke/github/GHPerson.java index 87cb8efaa7..b1be225965 100644 --- a/src/main/java/org/kohsuke/github/GHPerson.java +++ b/src/main/java/org/kohsuke/github/GHPerson.java @@ -81,7 +81,7 @@ public PagedIterable listRepositories() { public PagedIterable listRepositories(final int pageSize) { return new PagedIterable() { public PagedIterator _iterator(int pageSize) { - return new PagedIterator(root.retrieve().asIterator("/users/" + login + "/repos?per_page=" + pageSize, GHRepository[].class, pageSize)) { + return new PagedIterator(root.retrieve().asIterator("/users/" + login + "/repos", GHRepository[].class, pageSize)) { @Override protected void wrapUp(GHRepository[] page) { for (GHRepository c : page) @@ -89,7 +89,7 @@ protected void wrapUp(GHRepository[] page) { } }; } - }; + }.withPageSize(pageSize); } /** @@ -108,7 +108,7 @@ protected void wrapUp(GHRepository[] page) { public synchronized Iterable> iterateRepositories(final int pageSize) { return new Iterable>() { public Iterator> iterator() { - final Iterator pager = root.retrieve().asIterator("/users/" + login + "/repos?per_page="+pageSize,GHRepository[].class, pageSize); + final Iterator pager = root.retrieve().asIterator("/users/" + login + "/repos",GHRepository[].class, pageSize); return new Iterator>() { public boolean hasNext() { From c309c2cf1365ceb9d81c0d80fbd105322d07a1a8 Mon Sep 17 00:00:00 2001 From: Martin van Zijl Date: Thu, 9 Aug 2018 14:17:44 +1200 Subject: [PATCH 367/390] Fix for issue #426. Fix null pointer when deleting refs. --- src/main/java/org/kohsuke/github/GHRepository.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 3c80c499ff..cc0dc27717 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -815,7 +815,9 @@ public PagedIterable listRefs() throws IOException { public PagedIterator _iterator(int pageSize) { return new PagedIterator(root.retrieve().asIterator(url, GHRef[].class, pageSize)) { protected void wrapUp(GHRef[] page) { - // no-op + for(GHRef p: page) { + p.wrap(root); + } } }; } From b2b7dfaf379860e2bdf8313ad752f4c5d4825ef8 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 29 Aug 2018 19:05:19 -0700 Subject: [PATCH 368/390] Massaged the change to match the existing API design convention --- .../org/kohsuke/github/GHContentBuilder.java | 73 ++++++++++++++ .../github/GHContentUpdateRequest.java | 97 ------------------- .../java/org/kohsuke/github/GHRepository.java | 55 +++-------- .../org/kohsuke/github/PullRequestTest.java | 7 +- 4 files changed, 89 insertions(+), 143 deletions(-) create mode 100644 src/main/java/org/kohsuke/github/GHContentBuilder.java delete mode 100644 src/main/java/org/kohsuke/github/GHContentUpdateRequest.java diff --git a/src/main/java/org/kohsuke/github/GHContentBuilder.java b/src/main/java/org/kohsuke/github/GHContentBuilder.java new file mode 100644 index 0000000000..bd4a80c3af --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHContentBuilder.java @@ -0,0 +1,73 @@ +package org.kohsuke.github; + +import org.apache.commons.codec.binary.Base64; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; + +/** + * Used to create/update content. + * + * @author Kohsuke Kawaguchi + * @see GHRepository#createContent() + */ +public final class GHContentBuilder { + private final GHRepository repo; + private final Requester req; + private String path; + + GHContentBuilder(GHRepository repo) { + this.repo = repo; + this.req = new Requester(repo.root).method("PUT"); + } + + public GHContentBuilder path(String path) { + this.path = path; + req.with("path",path); + return this; + } + + public GHContentBuilder branch(String branch) { + req.with("branch", branch); + return this; + } + + /** + * Used when updating (but not creating a new content) to specify + * Thetblob SHA of the file being replaced. + */ + public GHContentBuilder sha(String sha) { + req.with("sha", sha); + return this; + } + + public GHContentBuilder content(byte[] content) { + req.with("content", Base64.encodeBase64String(content)); + return this; + } + + public GHContentBuilder content(String content) { + try { + return content(content.getBytes("UTF-8")); + } catch (UnsupportedEncodingException x) { + throw new AssertionError(); + } + } + + public GHContentBuilder message(String commitMessage) { + req.with("message", commitMessage); + return this; + } + + /** + * Commits a new content. + */ + public GHContentUpdateResponse commit() throws IOException { + GHContentUpdateResponse response = req.to(repo.getApiTailUrl("contents/" + path), GHContentUpdateResponse.class); + + response.getContent().wrap(repo); + response.getCommit().wrapUp(repo); + + return response; + } +} diff --git a/src/main/java/org/kohsuke/github/GHContentUpdateRequest.java b/src/main/java/org/kohsuke/github/GHContentUpdateRequest.java deleted file mode 100644 index 80bd0f6aa2..0000000000 --- a/src/main/java/org/kohsuke/github/GHContentUpdateRequest.java +++ /dev/null @@ -1,97 +0,0 @@ -package org.kohsuke.github; - -public class GHContentUpdateRequest { - private final String path; - private final String branch; - private final String sha; - private final byte[] content; - private final String commitMessage; - - public static GHContentUpdateRequest.Builder getBuilder() { - return new GHContentUpdateRequest.Builder(); - } - - public GHContentUpdateRequest(String path, String branch, String sha, byte[] content, String commitMessage) { - this.path = path; - this.branch = branch; - this.sha = sha; - this.content = content; - this.commitMessage = commitMessage; - } - - private GHContentUpdateRequest(Builder builder) { - this.path = builder.path; - this.branch = builder.branch; - this.sha = builder.sha; - this.content = builder.content; - this.commitMessage = builder.commitMessage; - } - - public static Builder newGHContentUpdateRequest() { - return new Builder(); - } - - public String getPath() { - return path; - } - - public String getBranch() { - return branch; - } - - public String getSha() { - return sha; - } - - public byte[] getContent() { - return content; - } - - public String getCommitMessage() { - return commitMessage; - } - - public static final class Builder { - private String path; - private String branch; - private String sha; - private byte[] content; - private String commitMessage; - - private Builder() { - } - - public GHContentUpdateRequest build() { - return new GHContentUpdateRequest(this); - } - - public Builder path(String path) { - this.path = path; - return this; - } - - public Builder branch(String branch) { - this.branch = branch; - return this; - } - - public Builder sha(String sha) { - this.sha = sha; - return this; - } - - public Builder content(byte[] content) { - this.content = content; - return this; - } - public Builder content(String content) { - this.content = content.getBytes(); - return this; - } - - public Builder commitMessage(String commitMessage) { - this.commitMessage = commitMessage; - return this; - } - } -} diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 302903ae8d..66688a1a6b 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -26,7 +26,6 @@ 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.codec.binary.Base64; import org.apache.commons.lang3.StringUtils; import java.io.FileNotFoundException; @@ -35,7 +34,6 @@ import java.io.InputStreamReader; import java.io.InterruptedIOException; import java.io.Reader; -import java.io.UnsupportedEncodingException; import java.net.URL; import java.util.AbstractSet; import java.util.ArrayList; @@ -1394,70 +1392,43 @@ public GHContent getReadme() throws IOException { return requester.to(getApiTailUrl("readme"), GHContent.class).wrap(this); } - public GHContentUpdateResponse createContent(GHContentUpdateRequest updateRequest) throws IOException { - return createContent(updateRequest.getContent(), updateRequest.getCommitMessage(), updateRequest.getPath(), updateRequest.getBranch(), updateRequest.getSha()); + /** + * Creates a new content, or update an existing content. + */ + public GHContentBuilder createContent() { + return new GHContentBuilder(this); } /** - * Use {@link GHContentUpdateRequest}. + * Use {@link #createContent()}. */ @Deprecated public GHContentUpdateResponse createContent(String content, String commitMessage, String path) throws IOException { - return createContent(content.getBytes(), commitMessage, path, null, null); + return createContent().content(content).message(commitMessage).path(path).commit(); } /** - * Use {@link GHContentUpdateRequest}. + * Use {@link #createContent()}. */ @Deprecated public GHContentUpdateResponse createContent(String content, String commitMessage, String path, String branch) throws IOException { - final byte[] payload; - try { - payload = content.getBytes("UTF-8"); - } catch (UnsupportedEncodingException ex) { - throw (IOException) new IOException("UTF-8 encoding is not supported").initCause(ex); - } - return createContent(payload, commitMessage, path, branch, null); + return createContent().content(content).message(commitMessage).path(path).branch(branch).commit(); } /** - * Use {@link GHContentUpdateRequest}. + * Use {@link #createContent()}. */ @Deprecated public GHContentUpdateResponse createContent(byte[] contentBytes, String commitMessage, String path) throws IOException { - return createContent(contentBytes, commitMessage, path, null, null); + return createContent().content(contentBytes).message(commitMessage).path(path).commit(); } /** - * Use {@link GHContentUpdateRequest}. + * Use {@link #createContent()}. */ @Deprecated public GHContentUpdateResponse createContent(byte[] contentBytes, String commitMessage, String path, String branch) throws IOException { - return createContent(contentBytes, commitMessage, path, branch, null); - } - - private GHContentUpdateResponse createContent(byte[] contentBytes, String commitMessage, String path, String branch, String sha1) throws IOException { - Requester requester = new Requester(root) - .with("path", path) - .with("message", commitMessage) - .with("content", Base64.encodeBase64String(contentBytes)) - .method("PUT"); - - if (sha1 != null) { - requester.with("sha", sha1); - } - - - if (branch != null) { - requester.with("branch", branch); - } - - GHContentUpdateResponse response = requester.to(getApiTailUrl("contents/" + path), GHContentUpdateResponse.class); - - response.getContent().wrap(this); - response.getCommit().wrapUp(this); - - return response; + return createContent().content(contentBytes).message(commitMessage).path(path).branch(branch).commit(); } public GHMilestone createMilestone(String title, String description) throws IOException { diff --git a/src/test/java/org/kohsuke/github/PullRequestTest.java b/src/test/java/org/kohsuke/github/PullRequestTest.java index 8bbada55bf..ceb741bd34 100644 --- a/src/test/java/org/kohsuke/github/PullRequestTest.java +++ b/src/test/java/org/kohsuke/github/PullRequestTest.java @@ -122,14 +122,13 @@ public void testUpdateContentSquashMerge() throws Exception { GHContentUpdateResponse response = getRepository().createContent(name, name, name, name); Thread.sleep(1000); - GHContentUpdateRequest updateRequest = GHContentUpdateRequest.getBuilder() + getRepository().createContent() .content(name + name) .path(name) .branch(name) - .commitMessage(name) + .message(name) .sha(response.getContent().getSha()) - .build(); - getRepository().createContent(updateRequest); + .commit(); GHPullRequest p = getRepository().createPullRequest(name, name, "master", "## test squash"); Thread.sleep(1000); p.merge("squash merge", null, GHPullRequest.MergeMethod.SQUASH); From 3fa70ac8411152a21f9fd286fbf68254e0964514 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 29 Aug 2018 19:05:46 -0700 Subject: [PATCH 369/390] doc improvement --- src/main/java/org/kohsuke/github/GHContentBuilder.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHContentBuilder.java b/src/main/java/org/kohsuke/github/GHContentBuilder.java index bd4a80c3af..cdc019f6d1 100644 --- a/src/main/java/org/kohsuke/github/GHContentBuilder.java +++ b/src/main/java/org/kohsuke/github/GHContentBuilder.java @@ -8,6 +8,9 @@ /** * Used to create/update content. * + *

+ * Call various methods to build up parameters, then call {@link #commit()} to make the change effective. + * * @author Kohsuke Kawaguchi * @see GHRepository#createContent() */ From ddc27e818b28b04b50d892c6683d111fbdc71056 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 29 Aug 2018 20:09:11 -0700 Subject: [PATCH 370/390] Let's not yet expose this new class because it's not final --- .../org/kohsuke/github/GHBranchProtection.java | 10 +++++----- .../kohsuke/github/GHBranchProtectionTest.java | 18 ++++++------------ 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHBranchProtection.java b/src/main/java/org/kohsuke/github/GHBranchProtection.java index a73d5ae2c4..423576fc1d 100644 --- a/src/main/java/org/kohsuke/github/GHBranchProtection.java +++ b/src/main/java/org/kohsuke/github/GHBranchProtection.java @@ -31,8 +31,8 @@ public class GHBranchProtection { private String url; @Preview @Deprecated - public RequiredSignatures enabledSignedCommits() throws IOException { - return requester().method("POST") + public void enabledSignedCommits() throws IOException { + requester().method("POST") .to(url + REQUIRE_SIGNATURES_URI, RequiredSignatures.class); } @@ -51,9 +51,9 @@ public RequiredReviews getRequiredReviews() { } @Preview @Deprecated - public RequiredSignatures getRequiredSignatures() throws IOException { + public boolean getRequiredSignatures() throws IOException { return requester().method("GET") - .to(url + REQUIRE_SIGNATURES_URI, RequiredSignatures.class); + .to(url + REQUIRE_SIGNATURES_URI, RequiredSignatures.class).enabled; } public RequiredStatusChecks getRequiredStatusChecks() { @@ -131,7 +131,7 @@ public int getRequiredReviewers() } } - public static class RequiredSignatures { + private static class RequiredSignatures { @JsonProperty private boolean enabled; diff --git a/src/test/java/org/kohsuke/github/GHBranchProtectionTest.java b/src/test/java/org/kohsuke/github/GHBranchProtectionTest.java index a6b711b6c0..19e42c51ba 100644 --- a/src/test/java/org/kohsuke/github/GHBranchProtectionTest.java +++ b/src/test/java/org/kohsuke/github/GHBranchProtectionTest.java @@ -4,7 +4,6 @@ import org.junit.Test; import org.kohsuke.github.GHBranchProtection.EnforceAdmins; import org.kohsuke.github.GHBranchProtection.RequiredReviews; -import org.kohsuke.github.GHBranchProtection.RequiredSignatures; import org.kohsuke.github.GHBranchProtection.RequiredStatusChecks; import java.io.FileNotFoundException; @@ -34,11 +33,11 @@ public void setUp() throws Exception { if (branch.isProtected()) { GHBranchProtection protection = branch.getProtection(); - if (protection.getRequiredSignatures().isEnabled()) { + if (protection.getRequiredSignatures()) { protection.disableSignedCommits(); } - assertFalse(protection.getRequiredSignatures().isEnabled()); + assertFalse(protection.getRequiredSignatures()); branch.disableProtection(); } @@ -93,17 +92,12 @@ public void testEnableRequireReviewsOnly() throws Exception { public void testSignedCommits() throws Exception { GHBranchProtection protection = branch.enableProtection().enable(); - RequiredSignatures signatures = protection.getRequiredSignatures(); - assertNotNull(signatures); - assertFalse(signatures.isEnabled()); + assertFalse(protection.getRequiredSignatures()); - signatures = protection.enabledSignedCommits(); - assertNotNull(signatures); - assertTrue(signatures.isEnabled()); + protection.enabledSignedCommits(); + assertTrue(protection.getRequiredSignatures()); protection.disableSignedCommits(); - signatures = protection.getRequiredSignatures(); - assertNotNull(signatures); - assertFalse(signatures.isEnabled()); + assertFalse(protection.getRequiredSignatures()); } } From 29a40d31b7739ec3fd46585a1ccc7bd7c569f247 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 29 Aug 2018 20:09:54 -0700 Subject: [PATCH 371/390] TAB -> space --- .../kohsuke/github/GHBranchProtection.java | 117 +++++++++--------- 1 file changed, 58 insertions(+), 59 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHBranchProtection.java b/src/main/java/org/kohsuke/github/GHBranchProtection.java index 423576fc1d..8420a531ad 100644 --- a/src/main/java/org/kohsuke/github/GHBranchProtection.java +++ b/src/main/java/org/kohsuke/github/GHBranchProtection.java @@ -8,41 +8,41 @@ import java.io.IOException; import java.util.Collection; -@SuppressFBWarnings(value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD", - "URF_UNREAD_FIELD" }, justification = "JSON API") +@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD", + "URF_UNREAD_FIELD"}, justification = "JSON API") public class GHBranchProtection { private static final String REQUIRE_SIGNATURES_URI = "/required_signatures"; - @JsonProperty("enforce_admins") - private EnforceAdmins enforceAdmins; + @JsonProperty("enforce_admins") + private EnforceAdmins enforceAdmins; - private GitHub root; + private GitHub root; - @JsonProperty("required_pull_request_reviews") - private RequiredReviews requiredReviews; + @JsonProperty("required_pull_request_reviews") + private RequiredReviews requiredReviews; - @JsonProperty("required_status_checks") - private RequiredStatusChecks requiredStatusChecks; + @JsonProperty("required_status_checks") + private RequiredStatusChecks requiredStatusChecks; - @JsonProperty - private Restrictions restrictions; + @JsonProperty + private Restrictions restrictions; - @JsonProperty - private String url; - - @Preview @Deprecated + @JsonProperty + private String url; + + @Preview @Deprecated public void enabledSignedCommits() throws IOException { requester().method("POST") .to(url + REQUIRE_SIGNATURES_URI, RequiredSignatures.class); } - @Preview @Deprecated + @Preview @Deprecated public void disableSignedCommits() throws IOException { requester().method("DELETE") .to(url + REQUIRE_SIGNATURES_URI); } - public EnforceAdmins getEnforceAdmins() { + public EnforceAdmins getEnforceAdmins() { return enforceAdmins; } @@ -78,11 +78,11 @@ private Requester requester() { } public static class EnforceAdmins { - @JsonProperty - private boolean enabled; + @JsonProperty + private boolean enabled; - @JsonProperty - private String url; + @JsonProperty + private String url; public String getUrl() { return url; @@ -91,23 +91,23 @@ public String getUrl() { public boolean isEnabled() { return enabled; } - } + } - public static class RequiredReviews { - @JsonProperty("dismissal_restrictions") - private Restrictions dismissalRestriction; + public static class RequiredReviews { + @JsonProperty("dismissal_restrictions") + private Restrictions dismissalRestriction; - @JsonProperty("dismiss_stale_reviews") - private boolean dismissStaleReviews; + @JsonProperty("dismiss_stale_reviews") + private boolean dismissStaleReviews; - @JsonProperty("require_code_owner_reviews") - private boolean requireCodeOwnerReviews; + @JsonProperty("require_code_owner_reviews") + private boolean requireCodeOwnerReviews; - @JsonProperty("required_approving_review_count") - private int requiredReviewers; + @JsonProperty("required_approving_review_count") + private int requiredReviewers; - @JsonProperty - private String url; + @JsonProperty + private String url; public Restrictions getDismissalRestrictions() { return dismissalRestriction; @@ -125,14 +125,13 @@ public boolean isRequireCodeOwnerReviews() { return requireCodeOwnerReviews; } - public int getRequiredReviewers() - { + public int getRequiredReviewers() { return requiredReviewers; } - } + } - private static class RequiredSignatures { - @JsonProperty + private static class RequiredSignatures { + @JsonProperty private boolean enabled; @JsonProperty @@ -145,17 +144,17 @@ public String getUrl() { public boolean isEnabled() { return enabled; } - } + } - public static class RequiredStatusChecks { - @JsonProperty - private Collection contexts; + public static class RequiredStatusChecks { + @JsonProperty + private Collection contexts; - @JsonProperty - private boolean strict; + @JsonProperty + private boolean strict; - @JsonProperty - private String url; + @JsonProperty + private String url; public Collection getContexts() { return contexts; @@ -168,23 +167,23 @@ public String getUrl() { public boolean isRequiresBranchUpToDate() { return strict; } - } + } - public static class Restrictions { - @JsonProperty - private Collection teams; + public static class Restrictions { + @JsonProperty + private Collection teams; - @JsonProperty("teams_url") - private String teamsUrl; + @JsonProperty("teams_url") + private String teamsUrl; - @JsonProperty - private String url; + @JsonProperty + private String url; - @JsonProperty - private Collection users; + @JsonProperty + private Collection users; - @JsonProperty("users_url") - private String usersUrl; + @JsonProperty("users_url") + private String usersUrl; public Collection getTeams() { return teams; @@ -205,5 +204,5 @@ public Collection getUsers() { public String getUsersUrl() { return usersUrl; } - } + } } From c988df13a8f976b3a6d86fc2de7542541be7fd12 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 29 Aug 2018 20:11:05 -0700 Subject: [PATCH 372/390] Use a short form --- .../java/org/kohsuke/github/GHBranchProtectionBuilder.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHBranchProtectionBuilder.java b/src/main/java/org/kohsuke/github/GHBranchProtectionBuilder.java index 61e9b70fea..822541a14d 100644 --- a/src/main/java/org/kohsuke/github/GHBranchProtectionBuilder.java +++ b/src/main/java/org/kohsuke/github/GHBranchProtectionBuilder.java @@ -44,8 +44,7 @@ public GHBranchProtectionBuilder addRequiredChecks(String... checks) { } public GHBranchProtectionBuilder dismissStaleReviews() { - dismissStaleReviews(true); - return this; + return dismissStaleReviews(true); } public GHBranchProtectionBuilder dismissStaleReviews(boolean v) { From 5e36377b36e05e3acc80f9c5dc0241837f19cfb0 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 29 Aug 2018 20:13:44 -0700 Subject: [PATCH 373/390] It appears LOKI preview is done and all those methods are now final --- src/main/java/org/kohsuke/github/GHBranch.java | 4 +--- src/main/java/org/kohsuke/github/GHRepository.java | 4 ++-- src/main/java/org/kohsuke/github/Previews.java | 1 - 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHBranch.java b/src/main/java/org/kohsuke/github/GHBranch.java index dbedcb64aa..e457fc243d 100644 --- a/src/main/java/org/kohsuke/github/GHBranch.java +++ b/src/main/java/org/kohsuke/github/GHBranch.java @@ -65,9 +65,8 @@ public URL getProtectionUrl() { return GitHub.parseURL(protection_url); } - @Preview @Deprecated public GHBranchProtection getProtection() throws IOException { - return root.retrieve().withPreview(LOKI).to(protection_url, GHBranchProtection.class).wrap(this); + return root.retrieve().to(protection_url, GHBranchProtection.class).wrap(this); } /** @@ -80,7 +79,6 @@ public String getSHA1() { /** * Disables branch protection and allows anyone with push access to push changes. */ - @Preview @Deprecated public void disableProtection() throws IOException { new Requester(root).method("DELETE").to(protection_url); } diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 3c80c499ff..2b89a491d1 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -1306,7 +1306,7 @@ public boolean remove(Object url) { */ public Map getBranches() throws IOException { Map r = new TreeMap(); - for (GHBranch p : root.retrieve().withPreview(LOKI).to(getApiTailUrl("branches"), GHBranch[].class)) { + for (GHBranch p : root.retrieve().to(getApiTailUrl("branches"), GHBranch[].class)) { p.wrap(this); r.put(p.getName(),p); } @@ -1314,7 +1314,7 @@ public Map getBranches() throws IOException { } public GHBranch getBranch(String name) throws IOException { - return root.retrieve().withPreview(LOKI).to(getApiTailUrl("branches/"+name),GHBranch.class).wrap(this); + return root.retrieve().to(getApiTailUrl("branches/"+name),GHBranch.class).wrap(this); } /** diff --git a/src/main/java/org/kohsuke/github/Previews.java b/src/main/java/org/kohsuke/github/Previews.java index f1686e24aa..41ac7e155b 100644 --- a/src/main/java/org/kohsuke/github/Previews.java +++ b/src/main/java/org/kohsuke/github/Previews.java @@ -4,7 +4,6 @@ * @author Kohsuke Kawaguchi */ /*package*/ class Previews { - static final String LOKI = "application/vnd.github.loki-preview+json"; static final String LUKE_CAGE = "application/vnd.github.luke-cage-preview+json"; static final String DRAX = "application/vnd.github.drax-preview+json"; static final String SQUIRREL_GIRL = "application/vnd.github.squirrel-girl-preview"; From 3b2802e36da20247bafa8bfe5da723c965a355e5 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 29 Aug 2018 20:18:00 -0700 Subject: [PATCH 374/390] minor doc improvement --- src/main/java/org/kohsuke/github/GHInvitation.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHInvitation.java b/src/main/java/org/kohsuke/github/GHInvitation.java index 6c285fefd1..fa0cacc67c 100644 --- a/src/main/java/org/kohsuke/github/GHInvitation.java +++ b/src/main/java/org/kohsuke/github/GHInvitation.java @@ -10,6 +10,10 @@ import java.util.Map; import java.util.TreeMap; +/** + * @see GitHub#getMyInvitations() + * @see GHRepository#listInvitations() + */ public class GHInvitation extends GHObject { /*package almost final*/ GitHub root; From 92a015ca4df1ccdf0d0b7b049e951bfe571fb09c Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 29 Aug 2018 20:18:10 -0700 Subject: [PATCH 375/390] Clear up import statements --- src/main/java/org/kohsuke/github/GHInvitation.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHInvitation.java b/src/main/java/org/kohsuke/github/GHInvitation.java index fa0cacc67c..213b7af3f1 100644 --- a/src/main/java/org/kohsuke/github/GHInvitation.java +++ b/src/main/java/org/kohsuke/github/GHInvitation.java @@ -2,13 +2,6 @@ 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.Map; -import java.util.TreeMap; /** * @see GitHub#getMyInvitations() From cbfe72a76eecd9b18af7bf6dd9ca339371fb3d65 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 29 Aug 2018 20:31:44 -0700 Subject: [PATCH 376/390] Fixed a broken test --- .../java/org/kohsuke/github/GHContentIntegrationTest.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/test/java/org/kohsuke/github/GHContentIntegrationTest.java b/src/test/java/org/kohsuke/github/GHContentIntegrationTest.java index b1ab9387f7..4b8bf72d63 100644 --- a/src/test/java/org/kohsuke/github/GHContentIntegrationTest.java +++ b/src/test/java/org/kohsuke/github/GHContentIntegrationTest.java @@ -53,10 +53,8 @@ public void testGetDirectoryContentTrailingSlash() throws Exception { @Test public void testCRUDContent() throws Exception { - ; GHContentUpdateResponse created = - repo.createContent("this is an awesome file I created\n", "Creating a file for integration tests.", createdFilename, - repo.getFileContent(createdFilename).getSha()); + repo.createContent("this is an awesome file I created\n", "Creating a file for integration tests.", createdFilename); GHContent createdContent = created.getContent(); assertNotNull(created.getCommit()); From 863995cb50013b6c6a7ef5c1e13f69ae964e60fe Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 29 Aug 2018 20:48:36 -0700 Subject: [PATCH 377/390] findbugs warning fix --- src/main/java/org/kohsuke/github/GHInvitation.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHInvitation.java b/src/main/java/org/kohsuke/github/GHInvitation.java index 213b7af3f1..bfa7de7be3 100644 --- a/src/main/java/org/kohsuke/github/GHInvitation.java +++ b/src/main/java/org/kohsuke/github/GHInvitation.java @@ -1,5 +1,7 @@ package org.kohsuke.github; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; + import java.io.IOException; import java.net.URL; @@ -7,6 +9,8 @@ * @see GitHub#getMyInvitations() * @see GHRepository#listInvitations() */ +@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", + "NP_UNWRITTEN_FIELD"}, justification = "JSON API") public class GHInvitation extends GHObject { /*package almost final*/ GitHub root; From ee4d514b665e09b5ef04ca4b7e63971e66b4707c Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 29 Aug 2018 20:48:44 -0700 Subject: [PATCH 378/390] close an opened stream --- src/main/java/org/kohsuke/github/GHRelease.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHRelease.java b/src/main/java/org/kohsuke/github/GHRelease.java index d49c0a2890..0df6b415b0 100644 --- a/src/main/java/org/kohsuke/github/GHRelease.java +++ b/src/main/java/org/kohsuke/github/GHRelease.java @@ -126,7 +126,12 @@ static GHRelease[] wrap(GHRelease[] releases, GHRepository owner) { * handling of the HTTP requests to github's API. */ public GHAsset uploadAsset(File file, String contentType) throws IOException { - return uploadAsset(file.getName(), new FileInputStream(file), contentType); + FileInputStream s = new FileInputStream(file); + try { + return uploadAsset(file.getName(), s, contentType); + } finally { + s.close(); + } } public GHAsset uploadAsset(String filename, InputStream stream, String contentType) throws IOException { From c44e5d2a876340ef2f26229f5940b494cfa75e98 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 29 Aug 2018 21:00:24 -0700 Subject: [PATCH 379/390] findbugs fix --- src/main/java/org/kohsuke/github/GHInvitation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GHInvitation.java b/src/main/java/org/kohsuke/github/GHInvitation.java index bfa7de7be3..74619ad6e0 100644 --- a/src/main/java/org/kohsuke/github/GHInvitation.java +++ b/src/main/java/org/kohsuke/github/GHInvitation.java @@ -10,7 +10,7 @@ * @see GHRepository#listInvitations() */ @SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", - "NP_UNWRITTEN_FIELD"}, justification = "JSON API") + "NP_UNWRITTEN_FIELD", "UUF_UNUSED_FIELD"}, justification = "JSON API") public class GHInvitation extends GHObject { /*package almost final*/ GitHub root; From 5194a361f49e382009ff3853010df9aec9b9a3ee Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 29 Aug 2018 21:05:21 -0700 Subject: [PATCH 380/390] [maven-release-plugin] prepare release github-api-1.94 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 3f134bed94..a0428a8a09 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.94-SNAPSHOT + 1.94 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - HEAD + github-api-1.94 From c8b0584127303533f9918cacdcb6eafb72e6c270 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 29 Aug 2018 21:05:31 -0700 Subject: [PATCH 381/390] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index a0428a8a09..3de2dfea24 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.94 + 1.95-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - github-api-1.94 + HEAD From 1c4b716f1a5f83f285b8a2029b334f3c942ddd71 Mon Sep 17 00:00:00 2001 From: Even Holthe Date: Mon, 1 Oct 2018 23:24:42 +0200 Subject: [PATCH 382/390] Add methods for adding/removing labels to GHIssue Fixes #456 --- src/main/java/org/kohsuke/github/GHIssue.java | 74 ++++++++++++++++++- 1 file changed, 71 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHIssue.java b/src/main/java/org/kohsuke/github/GHIssue.java index f7cfd9245c..2fde68a672 100644 --- a/src/main/java/org/kohsuke/github/GHIssue.java +++ b/src/main/java/org/kohsuke/github/GHIssue.java @@ -24,19 +24,20 @@ package org.kohsuke.github; +import static org.kohsuke.github.Previews.SQUIRREL_GIRL; + 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.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Date; +import java.util.HashSet; import java.util.List; import java.util.Locale; - -import static org.kohsuke.github.Previews.*; +import java.util.Set; /** * Represents an issue on GitHub. @@ -216,6 +217,73 @@ public void setLabels(String... labels) throws IOException { editIssue("labels",labels); } + /** + * Adds a label to the issue. If it does not exist in the {@link GHRepository}, it will be + * created with the specified color. If either {@code name} or {@code color} is null, it will + * be a NOP. + * + * @param name Name of the label + * @param color Hex code of the label, without # + */ + public void addLabel(String name, String color) throws IOException { + if (name != null && color != null) { + // All labels that we have seen + Set repoLabels = new HashSet(); + Set seenLabels = new HashSet(); + + // Check if label already exists + for (GHLabel repoLabel : getRepository().listLabels().asSet()) { + repoLabels.add(repoLabel.getName()); + } + + // Label does not exist + if (!repoLabels.contains(name)) { + GHLabel newLabel = getRepository().createLabel(name, color); + repoLabels.add(newLabel.getName()); + seenLabels.add(newLabel.getName()); + } + + // See if label exists on issue already + boolean foundInIssue = false; + + for (GHLabel existingIssueLabel : getLabels()) { + if (existingIssueLabel.getName().equalsIgnoreCase(name)) { + foundInIssue = true; + } + + seenLabels.add(existingIssueLabel.getName()); + } + + // If the label doesn't exist in the issue, add it + if (!foundInIssue) { + seenLabels.add(name); + setLabels(seenLabels.toArray(new String[0])); + } + } + } + + /** + * @see #removeLabel(String) + */ + public void removeLabel(Label label) throws IOException { + removeLabel(label.getName()); + } + + /** + * Remove a given label by name from this issue. + */ + public void removeLabel(String name) throws IOException { + Set newLabels = new HashSet(); + + for (Label existingLabel : labels) { + if (!existingLabel.getName().equalsIgnoreCase(name)) { + newLabels.add(existingLabel.getName()); + } + } + + setLabels(newLabels.toArray(new String[0])); + } + /** * Obtains all the comments associated with this issue. * From 9381471fbdc83f6d5e44dd54d101f8f36b2c07f2 Mon Sep 17 00:00:00 2001 From: "I329802 (Xeric)" Date: Thu, 11 Oct 2018 17:30:25 +0800 Subject: [PATCH 383/390] add request reviewers as attribute of GHPullRequest --- src/main/java/org/kohsuke/github/GHPullRequest.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index 16c3f953c6..53025f18cf 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -58,6 +58,9 @@ public class GHPullRequest extends GHIssue { private int changed_files; private String merge_commit_sha; + // pull request reviewers + private GHUser[] requested_reviewers; + /** * GitHub doesn't return some properties of {@link GHIssue} when requesting the GET on the 'pulls' API * route as opposed to 'issues' API route. This flag remembers whether we made the GET call on the 'issues' route @@ -76,6 +79,7 @@ GHPullRequest wrapUp(GitHub root) { if (base != null) base.wrapUp(root); if (head != null) head.wrapUp(root); if (merged_by != null) merged_by.wrapUp(root); + if (requested_reviewers != null) GHUser.wrap(requested_reviewers, root); return this; } @@ -219,6 +223,11 @@ public String getMergeCommitSha() throws IOException { return merge_commit_sha; } + public GHUser[] getRequestedReviewers() throws IOException { + populate(); + return requested_reviewers; + } + /** * Fully populate the data by retrieving missing data. * From 70251ea11e9cff37ce23901f5181be11756d690e Mon Sep 17 00:00:00 2001 From: Kanstantsin Shautsou Date: Sat, 20 Oct 2018 19:06:15 +0300 Subject: [PATCH 384/390] Fix memory leak. While repository object is active and code requests commits they are stored in Map. GHCommit.files contains huge String[]/char[] amount of data. The same could be applied to Milestones. --- src/main/java/org/kohsuke/github/GHRepository.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 2acc864123..f29181b02b 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -48,6 +48,7 @@ import java.util.Map; import java.util.Set; import java.util.TreeMap; +import java.util.WeakHashMap; import static java.util.Arrays.*; import static org.kohsuke.github.Previews.*; @@ -79,10 +80,10 @@ public class GHRepository extends GHObject { private boolean _private; private int forks_count, stargazers_count, watchers_count, size, open_issues_count, subscribers_count; private String pushed_at; - private Map milestones = new HashMap(); + private Map milestones = new WeakHashMap(); private String default_branch,language; - private Map commits = new HashMap(); + private Map commits = new WeakHashMap(); @SkipFromToString private GHRepoPermission permissions; From 1012dcd1942932291e93cebe600b1cbcef52a81a Mon Sep 17 00:00:00 2001 From: Manuel Recena Date: Thu, 25 Oct 2018 11:24:46 +0200 Subject: [PATCH 385/390] Added archived attribute in GHRepository. Updated the parent POM --- pom.xml | 3 ++- src/main/java/org/kohsuke/github/GHRepository.java | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 3de2dfea24..524901ec0d 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.kohsuke pom - 17 + 20 github-api @@ -36,6 +36,7 @@ maven-surefire-plugin + 2.22.1 2 diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index 2acc864123..af9380a7bc 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -74,7 +74,7 @@ public class GHRepository extends GHObject { private String git_url, ssh_url, clone_url, svn_url, mirror_url; private GHUser owner; // not fully populated. beware. - private boolean has_issues, has_wiki, fork, has_downloads, has_pages; + private boolean has_issues, has_wiki, fork, has_downloads, has_pages, archived; @JsonProperty("private") private boolean _private; private int forks_count, stargazers_count, watchers_count, size, open_issues_count, subscribers_count; @@ -393,6 +393,10 @@ public boolean isFork() { return fork; } + public boolean isArchived() { + return archived; + } + /** * Returns the number of all forks of this repository. * This not only counts direct forks, but also forks of forks, and so on. From 9345d3be31ddd8542a89786a4155b639bfd7d9cf Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Tue, 6 Nov 2018 07:49:02 -0800 Subject: [PATCH 386/390] Follow the convention in this library --- src/main/java/org/kohsuke/github/GHPullRequest.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHPullRequest.java b/src/main/java/org/kohsuke/github/GHPullRequest.java index 53025f18cf..b4098829b9 100644 --- a/src/main/java/org/kohsuke/github/GHPullRequest.java +++ b/src/main/java/org/kohsuke/github/GHPullRequest.java @@ -28,6 +28,7 @@ import java.net.URL; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.Date; import java.util.List; @@ -223,9 +224,9 @@ public String getMergeCommitSha() throws IOException { return merge_commit_sha; } - public GHUser[] getRequestedReviewers() throws IOException { + public List getRequestedReviewers() throws IOException { populate(); - return requested_reviewers; + return Collections.unmodifiableList(Arrays.asList(requested_reviewers)); } /** From 9a1bb09c9fe12b2b66ee9ae768a9b810beca07bb Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Tue, 6 Nov 2018 08:14:12 -0800 Subject: [PATCH 387/390] Massaging the changes. In particular, avoid the kind of addLabel() method that has lots of side effect and do multiple things. --- src/main/java/org/kohsuke/github/GHIssue.java | 85 +++++++++---------- src/main/java/org/kohsuke/github/GHLabel.java | 11 +++ 2 files changed, 51 insertions(+), 45 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GHIssue.java b/src/main/java/org/kohsuke/github/GHIssue.java index 2fde68a672..55cf54b81f 100644 --- a/src/main/java/org/kohsuke/github/GHIssue.java +++ b/src/main/java/org/kohsuke/github/GHIssue.java @@ -30,6 +30,7 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.io.IOException; import java.net.URL; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -218,70 +219,64 @@ public void setLabels(String... labels) throws IOException { } /** - * Adds a label to the issue. If it does not exist in the {@link GHRepository}, it will be - * created with the specified color. If either {@code name} or {@code color} is null, it will - * be a NOP. + * Adds labels to the issue. * - * @param name Name of the label - * @param color Hex code of the label, without # + * @param names Names of the label */ - public void addLabel(String name, String color) throws IOException { - if (name != null && color != null) { - // All labels that we have seen - Set repoLabels = new HashSet(); - Set seenLabels = new HashSet(); - - // Check if label already exists - for (GHLabel repoLabel : getRepository().listLabels().asSet()) { - repoLabels.add(repoLabel.getName()); - } + public void addLabels(String... names) throws IOException { + _addLabels(Arrays.asList(names)); + } - // Label does not exist - if (!repoLabels.contains(name)) { - GHLabel newLabel = getRepository().createLabel(name, color); - repoLabels.add(newLabel.getName()); - seenLabels.add(newLabel.getName()); - } + public void addLabels(GHLabel... labels) throws IOException { + addLabels(Arrays.asList(labels)); + } - // See if label exists on issue already - boolean foundInIssue = false; + public void addLabels(Collection labels) throws IOException { + _addLabels(GHLabel.toNames(labels)); + } - for (GHLabel existingIssueLabel : getLabels()) { - if (existingIssueLabel.getName().equalsIgnoreCase(name)) { - foundInIssue = true; - } + private void _addLabels(Collection names) throws IOException { + List newLabels = new ArrayList(); - seenLabels.add(existingIssueLabel.getName()); + for (GHLabel label : getLabels()) { + newLabels.add(label.getName()); } - - // If the label doesn't exist in the issue, add it - if (!foundInIssue) { - seenLabels.add(name); - setLabels(seenLabels.toArray(new String[0])); + for (String name : names) { + if (!newLabels.contains(name)) { + newLabels.add(name); + } } - } + setLabels(newLabels.toArray(new String[0])); } /** - * @see #removeLabel(String) + * Remove a given label by name from this issue. */ - public void removeLabel(Label label) throws IOException { - removeLabel(label.getName()); + public void removeLabels(String... names) throws IOException { + _removeLabels(Arrays.asList(names)); } /** - * Remove a given label by name from this issue. + * @see #removeLabels(String...) */ - public void removeLabel(String name) throws IOException { - Set newLabels = new HashSet(); + public void removeLabels(GHLabel... labels) throws IOException { + removeLabels(Arrays.asList(labels)); + } - for (Label existingLabel : labels) { - if (!existingLabel.getName().equalsIgnoreCase(name)) { - newLabels.add(existingLabel.getName()); + public void removeLabels(Collection labels) throws IOException { + _removeLabels(GHLabel.toNames(labels)); + } + + private void _removeLabels(Collection names) throws IOException { + List newLabels = new ArrayList(); + + for (GHLabel l : getLabels()) { + if (!names.contains(l.getName())) { + newLabels.add(l.getName()); + } } - } - setLabels(newLabels.toArray(new String[0])); + setLabels(newLabels.toArray(new String[0])); } /** diff --git a/src/main/java/org/kohsuke/github/GHLabel.java b/src/main/java/org/kohsuke/github/GHLabel.java index 3792fdcca3..9210bb5f5c 100644 --- a/src/main/java/org/kohsuke/github/GHLabel.java +++ b/src/main/java/org/kohsuke/github/GHLabel.java @@ -1,6 +1,9 @@ package org.kohsuke.github; import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; /** * @author Kohsuke Kawaguchi @@ -42,4 +45,12 @@ public void delete() throws IOException { public void setColor(String newColor) throws IOException { repo.root.retrieve().method("PATCH").with("name", name).with("color", newColor).to(url); } + + /*package*/ static Collection toNames(Collection labels) { + List r = new ArrayList(); + for (GHLabel l : labels) { + r.add(l.getName()); + } + return r; + } } From 40f012b03c25398c4336edfb1fdbcc7a1944e2e7 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Tue, 6 Nov 2018 08:35:48 -0800 Subject: [PATCH 388/390] rtyler no longer has 50 people he follows --- src/test/java/org/kohsuke/github/UserTest.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/test/java/org/kohsuke/github/UserTest.java b/src/test/java/org/kohsuke/github/UserTest.java index d35632fda2..9d1cfcbbac 100644 --- a/src/test/java/org/kohsuke/github/UserTest.java +++ b/src/test/java/org/kohsuke/github/UserTest.java @@ -14,17 +14,17 @@ public class UserTest extends AbstractGitHubApiTestBase { public void listFollowsAndFollowers() throws IOException { GHUser u = gitHub.getUser("rtyler"); assertNotEquals( - count50(u.listFollowers()), - count50(u.listFollows())); + count30(u.listFollowers()), + count30(u.listFollows())); } - private Set count50(PagedIterable l) { + private Set count30(PagedIterable l) { Set users = new HashSet(); PagedIterator itr = l.iterator(); - for (int i=0; i<50 && itr.hasNext(); i++) { + for (int i=0; i<30 && itr.hasNext(); i++) { users.add(itr.next()); } - assertEquals(50, users.size()); + assertEquals(30, users.size()); return users; } } From c1bab63ebdd9c93e49a5879331234de488e91590 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Tue, 6 Nov 2018 08:42:18 -0800 Subject: [PATCH 389/390] [maven-release-plugin] prepare release github-api-1.95 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 524901ec0d..9d599f2ade 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.95-SNAPSHOT + 1.95 GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - HEAD + github-api-1.95 From fad203a66df32f717ba27d9248e5996fbbf6378c Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Tue, 6 Nov 2018 08:42:28 -0800 Subject: [PATCH 390/390] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 9d599f2ade..15c85ed319 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ github-api - 1.95 + 1.96-SNAPSHOT GitHub API for Java http://github-api.kohsuke.org/ GitHub API for Java @@ -16,7 +16,7 @@ scm:git:git@github.com/kohsuke/${project.artifactId}.git scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git http://${project.artifactId}.kohsuke.org/ - github-api-1.95 + HEAD