diff --git a/src/main/java/org/kohsuke/github/GHBlob.java b/src/main/java/org/kohsuke/github/GHBlob.java new file mode 100644 index 000000000..7327fbfb1 --- /dev/null +++ b/src/main/java/org/kohsuke/github/GHBlob.java @@ -0,0 +1,63 @@ +package org.kohsuke.github; + +import org.apache.commons.codec.binary.Base64InputStream; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URL; + +/** + * @author Kanstantsin Shautsou + * @author Kohsuke Kawaguchi + * @see GHRepository#getBlob(String) + * @see Get a blob + */ +public class GHBlob { + private String content, encoding, url, sha; + private long size; + + /** + * 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); + } +} diff --git a/src/main/java/org/kohsuke/github/GHRepository.java b/src/main/java/org/kohsuke/github/GHRepository.java index f34ea8500..ac0d57b5f 100644 --- a/src/main/java/org/kohsuke/github/GHRepository.java +++ b/src/main/java/org/kohsuke/github/GHRepository.java @@ -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; @@ -817,6 +818,31 @@ public class GHRepository extends GHObject { return root.retrieve().to(url, GHTree.class).wrap(root); } + /** + * Obtains the metadata & the content of a blob. + * + *
+ * This method retrieves the whole content in memory, so beware when you are dealing with large BLOB. + * + * @see Get a blob + * @see #readBlob(String) + */ + public GHBlob getBlob(String blobSha) throws IOException { + String target = getApiTailUrl("git/blobs/" + blobSha); + return root.retrieve().to(target, GHBlob.class); + } + + /** + * Reads the content of a blob as a stream for better efficiency. + * + * @see Get a blob + * @see #getBlob(String) + */ + public InputStream readBlob(String blobSha) throws IOException { + String target = getApiTailUrl("git/blobs/" + blobSha); + return root.retrieve().withHeader("Accept","application/vnd.github.VERSION.raw").asStream(target); + } + /** * Gets a commit object in this repository. */ diff --git a/src/main/java/org/kohsuke/github/GHTreeEntry.java b/src/main/java/org/kohsuke/github/GHTreeEntry.java index e3d831c07..8359c40cd 100644 --- a/src/main/java/org/kohsuke/github/GHTreeEntry.java +++ b/src/main/java/org/kohsuke/github/GHTreeEntry.java @@ -54,14 +54,14 @@ public class GHTreeEntry { /** - * SHA1 of this object. + * SHA1 of this blob object. */ public String getSha() { return sha; } /** - * API URL to this Git data, such as + * API URL to this Git blob data, such as * https://api.github.com/repos/jenkinsci * /jenkins/git/commits/b72322675eb0114363a9a86e9ad5a170d1d07ac0 */ diff --git a/src/test/java/org/kohsuke/github/AppTest.java b/src/test/java/org/kohsuke/github/AppTest.java index 0a958418b..157d10540 100755 --- a/src/test/java/org/kohsuke/github/AppTest.java +++ b/src/test/java/org/kohsuke/github/AppTest.java @@ -12,6 +12,7 @@ import org.kohsuke.github.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; @@ -903,6 +904,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"));