Compare commits

..

17 Commits

Author SHA1 Message Date
Kohsuke Kawaguchi
3dbb516084 [maven-release-plugin] prepare release github-api-1.82 2016-12-17 07:50:48 -08:00
Kohsuke Kawaguchi
32177283b3 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.
2016-12-17 07:30:14 -08:00
Kohsuke Kawaguchi
3a66e90b7a Fixed issue #319
getApiUrl() is unreliable given that we collapse issue & PR into one
object.
2016-12-17 07:28:28 -08:00
Kohsuke Kawaguchi
a454fb10ec Tree traversal from commit & its associated tests 2016-12-17 07:21:31 -08:00
Kohsuke Kawaguchi
b5386a35ee Defining better traversal methods for apps that walk trees 2016-12-17 07:09:29 -08:00
Kohsuke Kawaguchi
11651da411 not always a blob, for example it could be a tree. 2016-12-17 07:04:31 -08:00
Kohsuke Kawaguchi
88d52c44ad Recording parent GHRepository 2016-12-17 07:03:40 -08:00
Kohsuke Kawaguchi
2d7d4bbd4e Merge pull request #320 with some additional changes 2016-12-17 06:56:41 -08:00
Kohsuke Kawaguchi
e6ee278fde Another version that directly reads BLOB without going through an intermediate object. 2016-12-17 06:55:44 -08:00
Kohsuke Kawaguchi
6380cf9ed0 Added a method to retrieve the actual bytes of BLOB
... which is probably more useful than the getContent() method
2016-12-17 06:47:24 -08:00
Kohsuke Kawaguchi
2e78dc52c7 Merge pull request #323 from jglick/bad-json
Fix syntactically malformed test JSON
2016-12-17 06:24:43 -08:00
Jesse Glick
c5009ab44b Fix syntactically malformed test JSON. 2016-12-16 15:04:10 -05:00
Kanstantsin Shautsou
0780e10fa2 Added ghRepo.getBlob(String) method
Signed-off-by: Kanstantsin Shautsou <kanstantsin.sha@gmail.com>
2016-12-13 15:28:08 +03:00
Kohsuke Kawaguchi
0731f63237 Added order parameter 2016-11-26 14:45:03 -08:00
Kohsuke Kawaguchi
a29896042b Merge pull request #315 from davidxia/dxia/patch1
Fix typos in javadocs
2016-11-26 14:38:45 -08:00
David Xia
68ebc08c9d Fix typos in javadocs
Replace "pagenated" with "paginated".
2016-11-26 00:44:52 -05:00
Kohsuke Kawaguchi
a1df526f93 [maven-release-plugin] prepare for next development iteration 2016-11-21 08:53:42 -08:00
16 changed files with 216 additions and 26 deletions

View File

@@ -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>

View 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);
}
}

View File

@@ -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"
*/

View File

@@ -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;

View File

@@ -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

View File

@@ -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) {

View File

@@ -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.

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -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.

View File

@@ -355,7 +355,7 @@ class Requester {
}
/**
* Loads pagenated resources.
* Loads paginated resources.
*
* Every iterator call reports a new batch.
*/

View File

@@ -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"));

View File

@@ -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",

View File

@@ -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",