From fd434292ad05e532561bdff2598be72e441ebff1 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Sun, 19 Apr 2015 17:40:39 -0700 Subject: [PATCH 01/31] [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 02/31] 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 03/31] 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 04/31] 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 05/31] 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 06/31] 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 07/31] 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 08/31] 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 09/31] 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 10/31] 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 11/31] 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 12/31] 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 13/31] 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 14/31] 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 15/31] 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 16/31] 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 17/31] 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 18/31] 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 19/31] 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 20/31] 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 21/31] 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 22/31] 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 23/31] 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 24/31] 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 25/31] 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 26/31] 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 27/31] 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 28/31] 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 29/31] 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 30/31] 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 31/31] [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