mirror of
https://github.com/jlengrand/github-api.git
synced 2026-03-12 08:21:22 +00:00
Compare commits
17 Commits
github-api
...
github-api
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3dbb516084 | ||
|
|
32177283b3 | ||
|
|
3a66e90b7a | ||
|
|
a454fb10ec | ||
|
|
b5386a35ee | ||
|
|
11651da411 | ||
|
|
88d52c44ad | ||
|
|
2d7d4bbd4e | ||
|
|
e6ee278fde | ||
|
|
6380cf9ed0 | ||
|
|
2e78dc52c7 | ||
|
|
c5009ab44b | ||
|
|
0780e10fa2 | ||
|
|
0731f63237 | ||
|
|
a29896042b | ||
|
|
68ebc08c9d | ||
|
|
a1df526f93 |
4
pom.xml
4
pom.xml
@@ -7,7 +7,7 @@
|
||||
</parent>
|
||||
|
||||
<artifactId>github-api</artifactId>
|
||||
<version>1.81</version>
|
||||
<version>1.82</version>
|
||||
<name>GitHub API for Java</name>
|
||||
<url>http://github-api.kohsuke.org/</url>
|
||||
<description>GitHub API for Java</description>
|
||||
@@ -16,7 +16,7 @@
|
||||
<connection>scm:git:git@github.com/kohsuke/${project.artifactId}.git</connection>
|
||||
<developerConnection>scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git</developerConnection>
|
||||
<url>http://${project.artifactId}.kohsuke.org/</url>
|
||||
<tag>github-api-1.81</tag>
|
||||
<tag>github-api-1.82</tag>
|
||||
</scm>
|
||||
|
||||
<distributionManagement>
|
||||
|
||||
64
src/main/java/org/kohsuke/github/GHBlob.java
Normal file
64
src/main/java/org/kohsuke/github/GHBlob.java
Normal file
@@ -0,0 +1,64 @@
|
||||
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 GHTreeEntry#asBlob()
|
||||
* @see GHRepository#getBlob(String)
|
||||
* @see <a href="https://developer.github.com/v3/git/blobs/#get-a-blob">Get a blob</a>
|
||||
*/
|
||||
public class GHBlob {
|
||||
private String content, encoding, url, sha;
|
||||
private long size;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,12 @@ public class GHCommit {
|
||||
|
||||
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 class GHCommit {
|
||||
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"
|
||||
*/
|
||||
|
||||
@@ -41,6 +41,11 @@ public class GHIssueSearchBuilder extends GHSearchBuilder<GHIssue> {
|
||||
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;
|
||||
|
||||
@@ -93,10 +93,10 @@ public abstract class GHPerson extends GHObject {
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads repository list in a pagenated fashion.
|
||||
* Loads repository list in a paginated fashion.
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
|
||||
@@ -213,7 +213,7 @@ public class GHPullRequest extends GHIssue {
|
||||
public PagedIterable<GHPullRequestFileDetail> listFiles() {
|
||||
return new PagedIterable<GHPullRequestFileDetail>() {
|
||||
public PagedIterator<GHPullRequestFileDetail> _iterator(int pageSize) {
|
||||
return new PagedIterator<GHPullRequestFileDetail>(root.retrieve().asIterator(String.format("%s/files", getApiURL()),
|
||||
return new PagedIterator<GHPullRequestFileDetail>(root.retrieve().asIterator(String.format("%s/files", getApiRoute()),
|
||||
GHPullRequestFileDetail[].class, pageSize)) {
|
||||
@Override
|
||||
protected void wrapUp(GHPullRequestFileDetail[] page) {
|
||||
@@ -247,7 +247,7 @@ public class GHPullRequest extends GHIssue {
|
||||
return new PagedIterable<GHPullRequestCommitDetail>() {
|
||||
public PagedIterator<GHPullRequestCommitDetail> _iterator(int pageSize) {
|
||||
return new PagedIterator<GHPullRequestCommitDetail>(root.retrieve().asIterator(
|
||||
String.format("%s/commits", getApiURL()),
|
||||
String.format("%s/commits", getApiRoute()),
|
||||
GHPullRequestCommitDetail[].class, pageSize)) {
|
||||
@Override
|
||||
protected void wrapUp(GHPullRequestCommitDetail[] page) {
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.io.Reader;
|
||||
@@ -504,7 +505,6 @@ public class GHRepository extends GHObject {
|
||||
}
|
||||
|
||||
private void modifyCollaborators(Collection<GHUser> users, String method) throws IOException {
|
||||
verifyMine();
|
||||
for (GHUser user : users) {
|
||||
new Requester(root).method(method).to(getApiTailUrl("collaborators/" + user.getLogin()));
|
||||
}
|
||||
@@ -799,7 +799,7 @@ public class GHRepository extends GHObject {
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -814,7 +814,32 @@ public class GHRepository extends GHObject {
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the metadata & the content of a blob.
|
||||
*
|
||||
* <p>
|
||||
* This method retrieves the whole content in memory, so beware when you are dealing with large BLOB.
|
||||
*
|
||||
* @see <a href="https://developer.github.com/v3/git/blobs/#get-a-blob">Get a blob</a>
|
||||
* @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 <a href="https://developer.github.com/v3/git/blobs/#get-a-blob">Get a blob</a>
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1092,11 +1117,6 @@ public class GHRepository extends GHObject {
|
||||
// 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.
|
||||
|
||||
@@ -57,6 +57,11 @@ public class GHRepositorySearchBuilder extends GHSearchBuilder<GHRepository> {
|
||||
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;
|
||||
|
||||
@@ -10,10 +10,12 @@ import java.util.List;
|
||||
* https://developer.github.com/v3/git/trees/
|
||||
*
|
||||
* @author Daniel Teixeira - https://github.com/ddtxra
|
||||
* @see GHCommit#getTree()
|
||||
* @see GHRepository#getTree(String)
|
||||
* @see GHTreeEntry#asTree()
|
||||
*/
|
||||
public class GHTree {
|
||||
/* package almost final */GitHub root;
|
||||
/* package almost final */GHRepository repo;
|
||||
|
||||
private boolean truncated;
|
||||
private String sha, url;
|
||||
@@ -34,6 +36,19 @@ public class GHTree {
|
||||
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.
|
||||
@@ -50,8 +65,11 @@ public class GHTree {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package org.kohsuke.github;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
@@ -10,6 +12,8 @@ import java.net.URL;
|
||||
* @see GHTree
|
||||
*/
|
||||
public class GHTreeEntry {
|
||||
/* package almost final */GHTree tree;
|
||||
|
||||
private String path, mode, type, sha, url;
|
||||
private long size;
|
||||
|
||||
@@ -44,7 +48,7 @@ public class GHTreeEntry {
|
||||
|
||||
/**
|
||||
* Gets the type such as:
|
||||
* "blob"
|
||||
* "blob", "tree", etc.
|
||||
*
|
||||
* @return The type
|
||||
*/
|
||||
@@ -68,4 +72,37 @@ public class GHTreeEntry {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,11 @@ public class GHUserSearchBuilder extends GHSearchBuilder<GHUser> {
|
||||
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;
|
||||
|
||||
@@ -6,7 +6,7 @@ import java.util.List;
|
||||
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.
|
||||
|
||||
@@ -355,7 +355,7 @@ class Requester {
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads pagenated resources.
|
||||
* Loads paginated resources.
|
||||
*
|
||||
* Every iterator call reports a new batch.
|
||||
*/
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.kohsuke.github.GHCommit.File;
|
||||
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;
|
||||
@@ -362,6 +363,11 @@ public class AppTest extends AbstractGitHubApiTestBase {
|
||||
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
|
||||
@@ -903,6 +909,26 @@ public class AppTest extends AbstractGitHubApiTestBase {
|
||||
}
|
||||
}
|
||||
|
||||
@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"));
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user