aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Barcenas2017-12-27 15:24:14 -0500
committerMatthias Sohn2018-03-24 08:29:29 -0400
commit569149b9dd4044017f83b50567491205b1738631 (patch)
tree845328e25636ec86d459c8560cdf8b196918442b
parente6d330a2817fe1a65e420e9c8677a1577fc550ea (diff)
downloadegit-github-569149b9dd4044017f83b50567491205b1738631.zip
egit-github-569149b9dd4044017f83b50567491205b1738631.tar.gz
egit-github-569149b9dd4044017f83b50567491205b1738631.tar.xz
Support diff/patch generation via the Github API
The Github API can generate .diff and .patch files server-side for individual commits and ranges of commits. This feature is very useful, as it permits one to fetch the contents of file changes without needing to download an entire repository. See: https://developer.github.com/v3/repos/commits/. This change adds support for these features to the CommitService. Bug: 529255 Change-Id: I9c700f0030578299283021b8f645d052bccca3c6 Signed-off-by: Christian Barcenas <christian@cbarcenas.com>
-rw-r--r--org.eclipse.egit.github.core.tests/src/org/eclipse/egit/github/core/tests/CommitServiceTest.java192
-rw-r--r--org.eclipse.egit.github.core.tests/src/org/eclipse/egit/github/core/tests/live/CommitTest.java72
-rw-r--r--org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/service/CommitService.java107
-rw-r--r--org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/service/GitHubService.java10
4 files changed, 366 insertions, 15 deletions
diff --git a/org.eclipse.egit.github.core.tests/src/org/eclipse/egit/github/core/tests/CommitServiceTest.java b/org.eclipse.egit.github.core.tests/src/org/eclipse/egit/github/core/tests/CommitServiceTest.java
index 1a378eb..eb1afa7 100644
--- a/org.eclipse.egit.github.core.tests/src/org/eclipse/egit/github/core/tests/CommitServiceTest.java
+++ b/org.eclipse.egit.github.core.tests/src/org/eclipse/egit/github/core/tests/CommitServiceTest.java
@@ -133,6 +133,80 @@ public class CommitServiceTest {
}
/**
+ * Get commit diff with null sha
+ *
+ * @throws IOException
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void getCommitDiffNullSha() throws IOException {
+ RepositoryId repo = new RepositoryId("o", "n");
+ service.getCommitDiff(repo, null);
+ }
+
+ /**
+ * Get commit diff with empty sha
+ *
+ * @throws IOException
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void getCommitDiffEmptySha() throws IOException {
+ RepositoryId repo = new RepositoryId("o", "n");
+ service.getCommitDiff(repo, "");
+ }
+
+ /**
+ * Get commit diff
+ *
+ * @throws IOException
+ */
+ @Test
+ public void getCommitDiff() throws IOException {
+ RepositoryId repo = new RepositoryId("o", "n");
+ service.getCommitDiff(repo, "abc");
+ GitHubRequest request = new GitHubRequest();
+ request.setUri("/repos/o/n/commits/abc");
+ request.setResponseContentType("application/vnd.github.v3.diff");
+ verify(client).getStream(request);
+ }
+
+ /**
+ * Get commit patch with null sha
+ *
+ * @throws IOException
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void getCommitPatchNullSha() throws IOException {
+ RepositoryId repo = new RepositoryId("o", "n");
+ service.getCommitPatch(repo, null);
+ }
+
+ /**
+ * Get commit patch with empty sha
+ *
+ * @throws IOException
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void getCommitPatchEmptySha() throws IOException {
+ RepositoryId repo = new RepositoryId("o", "n");
+ service.getCommitPatch(repo, "");
+ }
+
+ /**
+ * Get commit patch
+ *
+ * @throws IOException
+ */
+ @Test
+ public void getCommitPatch() throws IOException {
+ RepositoryId repo = new RepositoryId("o", "n");
+ service.getCommitPatch(repo, "abc");
+ GitHubRequest request = new GitHubRequest();
+ request.setUri("/repos/o/n/commits/abc");
+ request.setResponseContentType("application/vnd.github.v3.patch");
+ verify(client).getStream(request);
+ }
+
+ /**
* Get comments with null sha
*
* @throws IOException
@@ -331,6 +405,124 @@ public class CommitServiceTest {
}
/**
+ * Generate diff for commit comparison with null base
+ *
+ * @throws IOException
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void compareDiffNullBase() throws IOException {
+ RepositoryId repo = new RepositoryId("o", "n");
+ service.compareDiff(repo, null, "HEAD");
+ }
+
+ /**
+ * Generate diff for commit comparison with empty base
+ *
+ * @throws IOException
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void compareDiffEmptyBase() throws IOException {
+ RepositoryId repo = new RepositoryId("o", "n");
+ service.compareDiff(repo, "", "HEAD");
+ }
+
+ /**
+ * Generate diff for commit comparison with null head
+ *
+ * @throws IOException
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void compareDiffNullHead() throws IOException {
+ RepositoryId repo = new RepositoryId("o", "n");
+ service.compareDiff(repo, "HEAD~1", null);
+ }
+
+ /**
+ * Generate diff for commit comparison with empty head
+ *
+ * @throws IOException
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void compareDiffEmptyHead() throws IOException {
+ RepositoryId repo = new RepositoryId("o", "n");
+ service.compareDiff(repo, "HEAD~1", "");
+ }
+
+ /**
+ * Generate diff for commit comparison
+ *
+ * @throws IOException
+ */
+ @Test
+ public void compareDiff() throws IOException {
+ RepositoryId repo = new RepositoryId("o", "n");
+ service.compareDiff(repo, "v1", "HEAD");
+ GitHubRequest request = new GitHubRequest();
+ request.setResponseContentType("application/vnd.github.v3.diff");
+ request.setUri("/repos/o/n/compare/v1...HEAD");
+ verify(client).getStream(request);
+ }
+
+ /**
+ * Generate patch for commit comparison with null base
+ *
+ * @throws IOException
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void comparePatchNullBase() throws IOException {
+ RepositoryId repo = new RepositoryId("o", "n");
+ service.comparePatch(repo, null, "HEAD");
+ }
+
+ /**
+ * Generate patch for commit comparison with empty base
+ *
+ * @throws IOException
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void comparePatchEmptyBase() throws IOException {
+ RepositoryId repo = new RepositoryId("o", "n");
+ service.comparePatch(repo, "", "HEAD");
+ }
+
+ /**
+ * Generate patch for commit comparison with null head
+ *
+ * @throws IOException
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void comparePatchNullHead() throws IOException {
+ RepositoryId repo = new RepositoryId("o", "n");
+ service.comparePatch(repo, "HEAD~1", null);
+ }
+
+ /**
+ * Generate patch for commit comparison with empty head
+ *
+ * @throws IOException
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void comparePatchEmptyHead() throws IOException {
+ RepositoryId repo = new RepositoryId("o", "n");
+ service.comparePatch(repo, "HEAD~1", "");
+ }
+
+ /**
+ * Generate patch for commit comparison
+ *
+ * @throws IOException
+ */
+ @Test
+ public void comparePatch() throws IOException {
+ RepositoryId repo = new RepositoryId("o", "n");
+ service.comparePatch(repo, "v1", "HEAD");
+ GitHubRequest request = new GitHubRequest();
+ request.setResponseContentType("application/vnd.github.v3.patch");
+ request.setUri("/repos/o/n/compare/v1...HEAD");
+ verify(client).getStream(request);
+ }
+
+ /**
* Get statuses
*
* @throws IOException
diff --git a/org.eclipse.egit.github.core.tests/src/org/eclipse/egit/github/core/tests/live/CommitTest.java b/org.eclipse.egit.github.core.tests/src/org/eclipse/egit/github/core/tests/live/CommitTest.java
index b07565b..fb6a0e9 100644
--- a/org.eclipse.egit.github.core.tests/src/org/eclipse/egit/github/core/tests/live/CommitTest.java
+++ b/org.eclipse.egit.github.core.tests/src/org/eclipse/egit/github/core/tests/live/CommitTest.java
@@ -13,10 +13,14 @@ package org.eclipse.egit.github.core.tests.live;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import java.io.IOException;
+import java.io.InputStream;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
+import java.util.Scanner;
import java.util.Set;
import org.eclipse.egit.github.core.CommitComment;
@@ -107,4 +111,72 @@ public class CommitTest extends LiveTest {
assertNotNull(commit.getParents());
assertFalse(commit.getParents().isEmpty());
}
+
+ /**
+ * Test generating single-commit diff
+ *
+ * @throws IOException
+ */
+ @Test
+ public void singleCommitDiff() throws IOException {
+ CommitService service = new CommitService(client);
+ RepositoryId repo = RepositoryId.create("defunkt", "mustache");
+ String sha = "d8214ac6aef0759e112ff9ce8d2ef851b36969eb";
+ String firstLine = readLine(service.getCommitDiff(repo, sha), 0);
+ assertTrue("response is a diff", firstLine.startsWith("diff --git"));
+ }
+
+ /**
+ * Test generating single-commit patch
+ *
+ * @throws IOException
+ */
+ @Test
+ public void singleCommitPatch() throws IOException {
+ CommitService service = new CommitService(client);
+ RepositoryId repo = RepositoryId.create("defunkt", "mustache");
+ String sha = "d8214ac6aef0759e112ff9ce8d2ef851b36969eb";
+ String fourthLine = readLine(service.getCommitPatch(repo, sha), 3);
+ assertTrue("response is a patch", fourthLine.contains("[PATCH "));
+ }
+
+ /**
+ * Test generating multi-commit diff
+ *
+ * @throws IOException
+ */
+ @Test
+ public void multiCommitDiff() throws IOException {
+ CommitService service = new CommitService(client);
+ RepositoryId repo = RepositoryId.create("defunkt", "mustache");
+ String base = "d8214ac6aef0759e112ff9ce8d2ef851b36969eb";
+ String head = "7dd0a3773e7c65351cf3d75f17e9e91919bafa33";
+ String firstLine = readLine(service.compareDiff(repo, base, head), 0);
+ assertTrue("response is a diff", firstLine.startsWith("diff --git"));
+ }
+
+ /**
+ * Test generating multi-commit patch
+ *
+ * @throws IOException
+ */
+ @Test
+ public void multiCommitPatch() throws IOException {
+ CommitService service = new CommitService(client);
+ RepositoryId repo = RepositoryId.create("defunkt", "mustache");
+ String base = "d8214ac6aef0759e112ff9ce8d2ef851b36969eb";
+ String head = "7dd0a3773e7c65351cf3d75f17e9e91919bafa33";
+ String fourthLine = readLine(service.comparePatch(repo, base, head), 3);
+ assertTrue("response is a patch", fourthLine.contains("[PATCH "));
+ }
+
+ private String readLine(InputStream inStream, int i) throws IOException {
+ try (final Scanner sc = new Scanner(inStream)) {
+ sc.useDelimiter("\\n");
+ for (; i > 0; i--) {
+ sc.next();
+ }
+ return sc.next();
+ }
+ }
}
diff --git a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/service/CommitService.java b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/service/CommitService.java
index 75fb5ec..ad26d7c 100644
--- a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/service/CommitService.java
+++ b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/service/CommitService.java
@@ -21,6 +21,7 @@ import static org.eclipse.egit.github.core.client.PagedRequest.PAGE_SIZE;
import com.google.gson.reflect.TypeToken;
import java.io.IOException;
+import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -165,20 +166,57 @@ public class CommitService extends GitHubService {
*/
public RepositoryCommit getCommit(IRepositoryIdProvider repository,
String sha) throws IOException {
+ GitHubRequest request = getCommitRequest(repository, sha);
+ request.setType(RepositoryCommit.class);
+ return (RepositoryCommit) client.get(request).getBody();
+ }
+
+ /**
+ * Get diff for commit with given SHA-1 from given repository. It is the
+ * responsibility of the calling method to close the returned stream.
+ *
+ * @param repository
+ * @param sha
+ * @return diff stream
+ * @throws IOException
+ */
+ public InputStream getCommitDiff(IRepositoryIdProvider repository,
+ String sha) throws IOException {
+ GitHubRequest request = getCommitRequest(repository, sha);
+ request.setResponseContentType(ACCEPT_DIFF);
+ return client.getStream(request);
+ }
+
+ /**
+ * Get patch for commit with given SHA-1 from given repository. It is the
+ * responsibility of the calling method to close the returned stream.
+ *
+ * @param repository
+ * @param sha
+ * @return patch stream
+ * @throws IOException
+ */
+ public InputStream getCommitPatch(IRepositoryIdProvider repository,
+ String sha) throws IOException {
+ GitHubRequest request = getCommitRequest(repository, sha);
+ request.setResponseContentType(ACCEPT_PATCH);
+ return client.getStream(request);
+ }
+
+ private GitHubRequest getCommitRequest(IRepositoryIdProvider repository,
+ String sha) {
String id = getId(repository);
- if (sha == null)
+ if (sha == null) {
throw new IllegalArgumentException("Sha cannot be null"); //$NON-NLS-1$
- if (sha.length() == 0)
+ } else if (sha.length() == 0) {
throw new IllegalArgumentException("Sha cannot be empty"); //$NON-NLS-1$
+ }
StringBuilder uri = new StringBuilder(SEGMENT_REPOS);
uri.append('/').append(id);
uri.append(SEGMENT_COMMITS);
uri.append('/').append(sha);
- GitHubRequest request = createRequest();
- request.setUri(uri);
- request.setType(RepositoryCommit.class);
- return (RepositoryCommit) client.get(request).getBody();
+ return createRequest().setUri(uri);
}
/**
@@ -343,25 +381,64 @@ public class CommitService extends GitHubService {
*/
public RepositoryCommitCompare compare(IRepositoryIdProvider repository,
String base, String head) throws IOException {
+ GitHubRequest request = getCompareRequest(repository, base, head);
+ request.setType(RepositoryCommitCompare.class);
+ return (RepositoryCommitCompare) client.get(request).getBody();
+ }
+
+ /**
+ * Get diff between base and head commits. It is the responsibility of the
+ * calling method to close the returned stream.
+ *
+ * @param repository
+ * @param base
+ * @param head
+ * @return diff stream
+ * @throws IOException
+ */
+ public InputStream compareDiff(IRepositoryIdProvider repository,
+ String base, String head) throws IOException {
+ GitHubRequest request = getCompareRequest(repository, base, head);
+ request.setResponseContentType(ACCEPT_DIFF);
+ return client.getStream(request);
+ }
+
+ /**
+ * Get patch between base and head commits. It is the responsibility of the
+ * calling method to close the returned stream.
+ *
+ * @param repository
+ * @param base
+ * @param head
+ * @return patch stream
+ * @throws IOException
+ */
+ public InputStream comparePatch(IRepositoryIdProvider repository,
+ String base, String head) throws IOException {
+ GitHubRequest request = getCompareRequest(repository, base, head);
+ request.setResponseContentType(ACCEPT_PATCH);
+ return client.getStream(request);
+ }
+
+ private GitHubRequest getCompareRequest(IRepositoryIdProvider repository,
+ String base, String head) {
String id = getId(repository);
- if (base == null)
+ if (base == null) {
throw new IllegalArgumentException("Base cannot be null"); //$NON-NLS-1$
- if (base.length() == 0)
+ } else if (base.length() == 0) {
throw new IllegalArgumentException("Base cannot be empty"); //$NON-NLS-1$
-
- if (head == null)
+ }
+ if (head == null) {
throw new IllegalArgumentException("Head cannot be null"); //$NON-NLS-1$
- if (head.length() == 0)
+ } else if (head.length() == 0) {
throw new IllegalArgumentException("Head cannot be empty"); //$NON-NLS-1$
+ }
StringBuilder uri = new StringBuilder(SEGMENT_REPOS);
uri.append('/').append(id);
uri.append(SEGMENT_COMPARE);
uri.append('/').append(base).append("...").append(head); //$NON-NLS-1$
- GitHubRequest request = createRequest();
- request.setType(RepositoryCommitCompare.class);
- request.setUri(uri);
- return (RepositoryCommitCompare) client.get(request).getBody();
+ return createRequest().setUri(uri);
}
/**
diff --git a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/service/GitHubService.java b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/service/GitHubService.java
index 25fc3ab..9d9ebc2 100644
--- a/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/service/GitHubService.java
+++ b/org.eclipse.egit.github.core/src/org/eclipse/egit/github/core/service/GitHubService.java
@@ -52,6 +52,16 @@ public abstract class GitHubService {
public static final String ACCEPT_FULL = "application/vnd.github.v3.full+json"; //$NON-NLS-1$
/**
+ * Accept header for diff response
+ */
+ public static final String ACCEPT_DIFF = "application/vnd.github.v3.diff"; //$NON-NLS-1$
+
+ /**
+ * Accept header for patch response
+ */
+ public static final String ACCEPT_PATCH = "application/vnd.github.v3.patch"; //$NON-NLS-1$
+
+ /**
* Accept header to use preview features of the 'ironman' release.
* @see <a href="https://developer.github.com/changes">https://developer.github.com/changes</a>
* @since 4.2