/*******************************************************************************
* Copyright (c) 2011, 2014 IBM Corporation and others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.orion.server.tests.servlets.git;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.orion.internal.server.core.metastore.SimpleMetaStore;
import org.eclipse.orion.server.core.IOUtilities;
import org.eclipse.orion.server.core.ProtocolConstants;
import org.eclipse.orion.server.core.ServerStatus;
import org.eclipse.orion.server.git.GitConstants;
import org.eclipse.orion.server.git.objects.Diff;
import org.eclipse.orion.server.git.servlets.GitServlet;
import org.eclipse.osgi.util.NLS;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Test;
import org.xml.sax.SAXException;
import com.meterware.httpunit.GetMethodWebRequest;
import com.meterware.httpunit.PostMethodWebRequest;
import com.meterware.httpunit.WebConversation;
import com.meterware.httpunit.WebRequest;
import com.meterware.httpunit.WebResponse;
public class GitDiffTest extends GitTest {
@Test
public void testNoDiff() throws Exception {
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
String projectName = getMethodName().concat("Project");
JSONObject project = createProjectOrLink(workspaceLocation, projectName, gitDir.toString());
JSONObject gitSection = project.getJSONObject(GitConstants.KEY_GIT);
String gitDiffUri = gitSection.getString(GitConstants.KEY_DIFF);
String[] parts = getDiff(gitDiffUri);
assertEquals("", parts[1]);
}
@Test
public void testDiffAlreadyModified() throws Exception {
Writer w = new OutputStreamWriter(new FileOutputStream(testFile), "UTF-8");
try {
w.write("hello");
} finally {
w.close();
}
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
String projectName = getMethodName().concat("Project");
JSONObject project = createProjectOrLink(workspaceLocation, projectName, gitDir.toString());
JSONObject gitSection = project.getJSONObject(GitConstants.KEY_GIT);
String gitDiffUri = gitSection.getString(GitConstants.KEY_DIFF);
String[] parts = getDiff(gitDiffUri);
StringBuilder sb = new StringBuilder();
sb.append("diff --git a/test.txt b/test.txt").append("\n");
sb.append("index 30d74d2..b6fc4c6 100644").append("\n");
sb.append("--- a/test.txt").append("\n");
sb.append("+++ b/test.txt").append("\n");
sb.append("@@ -1 +1 @@").append("\n");
sb.append("-test").append("\n");
sb.append("\\ No newline at end of file").append("\n");
sb.append("+hello").append("\n");
sb.append("\\ No newline at end of file").append("\n");
assertEquals(sb.toString(), parts[1]);
}
@Test
public void testDiffModifiedByOrion() throws Exception {
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
String projectName = getMethodName().concat("Project");
JSONObject project = createProjectOrLink(workspaceLocation, projectName, gitDir.toString());
JSONObject testTxt = getChild(project, "test.txt");
modifyFile(testTxt, "hello");
JSONObject gitSection = project.getJSONObject(GitConstants.KEY_GIT);
String gitDiffUri = gitSection.getString(GitConstants.KEY_DIFF);
String[] parts = getDiff(gitDiffUri);
StringBuilder sb = new StringBuilder();
sb.append("diff --git a/test.txt b/test.txt").append("\n");
sb.append("index 30d74d2..b6fc4c6 100644").append("\n");
sb.append("--- a/test.txt").append("\n");
sb.append("+++ b/test.txt").append("\n");
sb.append("@@ -1 +1 @@").append("\n");
sb.append("-test").append("\n");
sb.append("\\ No newline at end of file").append("\n");
sb.append("+hello").append("\n");
sb.append("\\ No newline at end of file").append("\n");
assertEquals(sb.toString(), parts[1]);
}
@Test
public void testDiffFilter() throws Exception {
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
String projectName = getMethodName().concat("Project");
JSONObject project = createProjectOrLink(workspaceLocation, projectName, gitDir.toString());
JSONObject testTxt = getChild(project, "test.txt");
modifyFile(testTxt, "hi");
JSONObject folder1 = getChild(project, "folder");
JSONObject folderTxt = getChild(folder1, "folder.txt");
modifyFile(folderTxt, "folder change");
String[] parts = getDiff(folder1.getJSONObject(GitConstants.KEY_GIT).getString(GitConstants.KEY_DIFF));
StringBuilder sb = new StringBuilder();
sb.append("diff --git a/folder/folder.txt b/folder/folder.txt").append("\n");
sb.append("index 0119635..95c4c65 100644").append("\n");
sb.append("--- a/folder/folder.txt").append("\n");
sb.append("+++ b/folder/folder.txt").append("\n");
sb.append("@@ -1 +1 @@").append("\n");
sb.append("-folder").append("\n");
sb.append("\\ No newline at end of file").append("\n");
sb.append("+folder change").append("\n");
sb.append("\\ No newline at end of file").append("\n");
assertEquals(sb.toString(), parts[1]);
String gitDiffUri = testTxt.getJSONObject(GitConstants.KEY_GIT).getString(GitConstants.KEY_DIFF);
parts = getDiff(gitDiffUri);
assertDiffUris(gitDiffUri, new String[] {"test", "hi", "test"}, new JSONObject(parts[0]));
sb.setLength(0);
sb.append("diff --git a/test.txt b/test.txt").append("\n");
sb.append("index 30d74d2..32f95c0 100644").append("\n");
sb.append("--- a/test.txt").append("\n");
sb.append("+++ b/test.txt").append("\n");
sb.append("@@ -1 +1 @@").append("\n");
sb.append("-test").append("\n");
sb.append("\\ No newline at end of file").append("\n");
sb.append("+hi").append("\n");
sb.append("\\ No newline at end of file").append("\n");
assertEquals(sb.toString(), parts[1]);
}
@Test
public void testDiffPaths() throws Exception {
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
String projectName = getMethodName().concat("Project");
JSONObject project = createProjectOrLink(workspaceLocation, projectName, gitDir.toString());
JSONObject testTxt = getChild(project, "test.txt");
modifyFile(testTxt, "hi");
JSONObject folder1 = getChild(project, "folder");
JSONObject folderTxt = getChild(folder1, "folder.txt");
modifyFile(folderTxt, "folder change");
WebRequest request = getGetGitDiffRequest(project.getJSONObject(GitConstants.KEY_GIT).getString(GitConstants.KEY_DIFF) + "?parts=diff", new String[] {"folder/folder.txt"});
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
StringBuilder sb1 = new StringBuilder();
sb1.append("diff --git a/folder/folder.txt b/folder/folder.txt").append("\n");
sb1.append("index 0119635..95c4c65 100644").append("\n");
sb1.append("--- a/folder/folder.txt").append("\n");
sb1.append("+++ b/folder/folder.txt").append("\n");
sb1.append("@@ -1 +1 @@").append("\n");
sb1.append("-folder").append("\n");
sb1.append("\\ No newline at end of file").append("\n");
sb1.append("+folder change").append("\n");
sb1.append("\\ No newline at end of file").append("\n");
assertEquals(sb1.toString(), response.getText());
request = getGetGitDiffRequest(project.getJSONObject(GitConstants.KEY_GIT).getString(GitConstants.KEY_DIFF) + "?parts=diff", new String[] {"test.txt"});
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
StringBuilder sb2 = new StringBuilder();
sb2.append("diff --git a/test.txt b/test.txt").append("\n");
sb2.append("index 30d74d2..32f95c0 100644").append("\n");
sb2.append("--- a/test.txt").append("\n");
sb2.append("+++ b/test.txt").append("\n");
sb2.append("@@ -1 +1 @@").append("\n");
sb2.append("-test").append("\n");
sb2.append("\\ No newline at end of file").append("\n");
sb2.append("+hi").append("\n");
sb2.append("\\ No newline at end of file").append("\n");
assertEquals(sb2.toString(), response.getText());
request = getGetGitDiffRequest(project.getJSONObject(GitConstants.KEY_GIT).getString(GitConstants.KEY_DIFF) + "?parts=diff", new String[] {"folder/folder.txt", "test.txt"});
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
sb1.append(sb2);
assertEquals(sb1.toString(), response.getText());
}
@Test
public void testDiffCached() throws Exception {
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
String projectName = getMethodName().concat("Project");
JSONObject project = createProjectOrLink(workspaceLocation, projectName, gitDir.toString());
JSONObject testTxt = getChild(project, "test.txt");
modifyFile(testTxt, "stage me");
addFile(testTxt);
String gitDiffUri = getDiffCachedLocation(testTxt);
String[] parts = getDiff(gitDiffUri);
assertDiffUris(gitDiffUri, new String[] {"test", "stage me", "test"}, new JSONObject(parts[0]));
StringBuilder sb = new StringBuilder();
sb.append("diff --git a/test.txt b/test.txt").append("\n");
sb.append("index 30d74d2..b874aa3 100644").append("\n");
sb.append("--- a/test.txt").append("\n");
sb.append("+++ b/test.txt").append("\n");
sb.append("@@ -1 +1 @@").append("\n");
sb.append("-test").append("\n");
sb.append("\\ No newline at end of file").append("\n");
sb.append("+stage me").append("\n");
sb.append("\\ No newline at end of file").append("\n");
assertEquals(sb.toString(), parts[1]);
}
@Test
public void testDiffCommits() throws Exception {
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
String projectName = getMethodName().concat("Project");
JSONObject project = createProjectOrLink(workspaceLocation, projectName, gitDir.toString());
JSONObject testTxt = getChild(project, "test.txt");
modifyFile(testTxt, "first change");
addFile(testTxt);
JSONObject commit1 = commitFile(testTxt, "commit1");
// modify again
modifyFile(testTxt, "second change");
addFile(testTxt);
// commit2
JSONObject commit2 = commitFile(testTxt, "commit2");
String testTxtHeadLocation = testTxt.getJSONObject(GitConstants.KEY_GIT).getString(GitConstants.KEY_HEAD);
JSONObject testTxtInitialCommit = findCommitByMessage(testTxtHeadLocation, "Initial commit");
String gitDiffUri = getDiffLocation(testTxtInitialCommit.getString(GitConstants.KEY_DIFF), commit1.getString(ProtocolConstants.KEY_NAME));
String[] parts = getDiff(gitDiffUri);
StringBuilder sb = new StringBuilder();
sb.append("diff --git a/test.txt b/test.txt").append("\n");
sb.append("index 30d74d2..3c26ed4 100644").append("\n");
sb.append("--- a/test.txt").append("\n");
sb.append("+++ b/test.txt").append("\n");
sb.append("@@ -1 +1 @@").append("\n");
sb.append("-test").append("\n");
sb.append("\\ No newline at end of file").append("\n");
sb.append("+first change").append("\n");
sb.append("\\ No newline at end of file").append("\n");
assertEquals(sb.toString(), parts[1]);
gitDiffUri = getDiffLocation(testTxtInitialCommit.getString(GitConstants.KEY_DIFF), commit2.getString(ProtocolConstants.KEY_NAME));
parts = getDiff(gitDiffUri);
sb.setLength(0);
sb.append("diff --git a/test.txt b/test.txt").append("\n");
sb.append("index 30d74d2..58bcb48 100644").append("\n");
sb.append("--- a/test.txt").append("\n");
sb.append("+++ b/test.txt").append("\n");
sb.append("@@ -1 +1 @@").append("\n");
sb.append("-test").append("\n");
sb.append("\\ No newline at end of file").append("\n");
sb.append("+second change").append("\n");
sb.append("\\ No newline at end of file").append("\n");
assertEquals(sb.toString(), parts[1]);
}
@Test
public void testDiffCommitWithWorkingTree() throws Exception {
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
String projectName = getMethodName().concat("Project");
JSONObject project = createProjectOrLink(workspaceLocation, projectName, gitDir.toString());
JSONObject testTxt = getChild(project, "test.txt");
modifyFile(testTxt, "first change");
addFile(testTxt);
JSONObject commit1 = commitFile(testTxt, "commit1");
modifyFile(testTxt, "second change");
addFile(testTxt);
JSONObject commit2 = commitFile(testTxt, "commit2");
// modify again and leave the change in the working tree only
modifyFile(testTxt, "third change (in tree only)");
String commit1DiffUri = commit1.getString(GitConstants.KEY_DIFF);
String[] parts = getDiff(commit1DiffUri);
StringBuilder sb = new StringBuilder();
sb.append("diff --git a/test.txt b/test.txt").append("\n");
sb.append("index 3c26ed4..4cb5d38 100644").append("\n");
sb.append("--- a/test.txt").append("\n");
sb.append("+++ b/test.txt").append("\n");
sb.append("@@ -1 +1 @@").append("\n");
sb.append("-first change").append("\n");
sb.append("\\ No newline at end of file").append("\n");
sb.append("+third change (in tree only)").append("\n");
sb.append("\\ No newline at end of file").append("\n");
assertEquals(sb.toString(), parts[1]);
String commit2DiffUri = commit2.getString(GitConstants.KEY_DIFF);
parts = getDiff(commit2DiffUri);
sb = new StringBuilder();
sb.append("diff --git a/test.txt b/test.txt").append("\n");
sb.append("index 58bcb48..4cb5d38 100644").append("\n");
sb.append("--- a/test.txt").append("\n");
sb.append("+++ b/test.txt").append("\n");
sb.append("@@ -1 +1 @@").append("\n");
sb.append("-second change").append("\n");
sb.append("\\ No newline at end of file").append("\n");
sb.append("+third change (in tree only)").append("\n");
sb.append("\\ No newline at end of file").append("\n");
assertEquals(sb.toString(), parts[1]);
}
@Test
public void testDiffBranchWithWorkingTree() throws Exception {
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
String projectName = getMethodName().concat("Project");
JSONObject project = createProjectOrLink(workspaceLocation, projectName, gitDir.toString());
JSONObject clone = getCloneForGitResource(project);
String branchesLocation = clone.getString(GitConstants.KEY_BRANCH);
JSONObject testTxt = getChild(project, "test.txt");
modifyFile(testTxt, "change in master");
addFile(testTxt);
commitFile(testTxt, "commit");
modifyFile(testTxt, "change in the working tree");
String[] parts = getDiff(findDiffLocationForBranchByName(branchesLocation, Constants.MASTER));
StringBuilder sb = new StringBuilder();
sb.append("diff --git a/test.txt b/test.txt").append("\n");
sb.append("index 597c638..5ae4d45 100644").append("\n");
sb.append("--- a/test.txt").append("\n");
sb.append("+++ b/test.txt").append("\n");
sb.append("@@ -1 +1 @@").append("\n");
sb.append("-change in master").append("\n");
sb.append("\\ No newline at end of file").append("\n");
sb.append("+change in the working tree").append("\n");
sb.append("\\ No newline at end of file").append("\n");
assertEquals(sb.toString(), parts[1]);
}
@Test
public void testDiffPost() throws Exception {
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
String projectName = getMethodName().concat("Project");
JSONObject project = createProjectOrLink(workspaceLocation, projectName, gitDir.toString());
JSONObject gitSection = project.getJSONObject(GitConstants.KEY_GIT);
JSONObject testTxt = getChild(project, "test.txt");
modifyFile(testTxt, "change");
addFile(testTxt);
commitFile(testTxt, "commit1", false);
String testTxtHeadLocation = testTxt.getJSONObject(GitConstants.KEY_GIT).getString(GitConstants.KEY_HEAD);
JSONObject testTxtInitialCommit = findCommitByMessage(testTxtHeadLocation, "Initial commit");
String location = getDiffLocation(testTxtInitialCommit.getString(GitConstants.KEY_DIFF), Constants.HEAD);
String diffScope = URLEncoder.encode(testTxtInitialCommit.getString(ProtocolConstants.KEY_NAME) + ".." + Constants.HEAD, "UTF-8");
String expectedLocation = gitSection.getString(GitConstants.KEY_DIFF).replaceAll(GitConstants.KEY_DIFF_DEFAULT, diffScope);
expectedLocation += "test.txt";
assertEquals(expectedLocation, location);
WebRequest request = getGetRequest(location);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
String[] parts = parseMultiPartResponse(response);
assertDiffUris(expectedLocation, new String[] {"test", "change", "test"}, new JSONObject(parts[0]));
StringBuilder sb = new StringBuilder();
sb.append("diff --git a/test.txt b/test.txt").append("\n");
sb.append("index 30d74d2..8013df8 100644").append("\n");
sb.append("--- a/test.txt").append("\n");
sb.append("+++ b/test.txt").append("\n");
sb.append("@@ -1 +1 @@").append("\n");
sb.append("-test").append("\n");
sb.append("\\ No newline at end of file").append("\n");
sb.append("+change").append("\n");
sb.append("\\ No newline at end of file").append("\n");
assertEquals(sb.toString(), parts[1]);
}
@Test
public void testDiffParts() throws Exception {
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
String projectName = getMethodName().concat("Project");
JSONObject project = createProjectOrLink(workspaceLocation, projectName, gitDir.toString());
JSONObject testTxt = getChild(project, "test.txt");
modifyFile(testTxt, "change");
addFile(testTxt);
JSONObject commit = commitFile(testTxt, "commit");
String testTxtHeadLocation = testTxt.getJSONObject(GitConstants.KEY_GIT).getString(GitConstants.KEY_HEAD);
JSONObject testTxtInitialCommit = findCommitByMessage(testTxtHeadLocation, "Initial commit");
String location = getDiffLocation(testTxtInitialCommit.getString(GitConstants.KEY_DIFF), commit.getString(ProtocolConstants.KEY_NAME));
String[] parts = getDiff(location + "?parts=uris,diff");
assertDiffUris(location, new String[] {"test", "change", "test"}, new JSONObject(parts[0]));
StringBuilder sb = new StringBuilder();
sb.append("diff --git a/test.txt b/test.txt").append("\n");
sb.append("index 30d74d2..8013df8 100644").append("\n");
sb.append("--- a/test.txt").append("\n");
sb.append("+++ b/test.txt").append("\n");
sb.append("@@ -1 +1 @@").append("\n");
sb.append("-test").append("\n");
sb.append("\\ No newline at end of file").append("\n");
sb.append("+change").append("\n");
sb.append("\\ No newline at end of file").append("\n");
assertEquals(sb.toString(), parts[1]);
parts = getDiff(location + "?parts=diff,uris");
assertDiffUris(location, new String[] {"test", "change", "test"}, new JSONObject(parts[0]));
assertEquals(sb.toString(), parts[1]);
WebRequest request = getGetRequest(location + "?parts=diff");
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
assertEquals(sb.toString(), response.getText());
request = getGetRequest(location + "?parts=uris");
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
assertDiffUris(location, new String[] {"test", "change", "test"}, new JSONObject(response.getText()));
}
@Test
public void testDiffUntrackedUri() throws Exception {
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
String projectName = getMethodName().concat("Project");
JSONObject project = createProjectOrLink(workspaceLocation, projectName, gitDir.toString());
String fileName = "new.txt";
WebRequest request = getPostFilesRequest("", getNewFileJSON(fileName).toString(), fileName);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_CREATED, response.getResponseCode());
JSONObject newTxt = getChild(project, "new.txt");
String gitDiffUri = newTxt.getJSONObject(GitConstants.KEY_GIT).getString(GitConstants.KEY_DIFF);
request = getGetRequest(gitDiffUri + "?parts=uris");
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// modified assertDiffUris(...);
JSONObject jsonPart = new JSONObject(response.getText());
assertEquals(Diff.TYPE, jsonPart.getString(ProtocolConstants.KEY_TYPE));
String fileOldUri = jsonPart.getString(GitConstants.KEY_COMMIT_OLD);
request = getGetRequest(fileOldUri);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_NOT_FOUND, response.getResponseCode());
String fileNewUri = jsonPart.getString(GitConstants.KEY_COMMIT_NEW);
request = getGetRequest(fileNewUri);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
assertEquals("", response.getText());
String fileBaseUri = jsonPart.getString(GitConstants.KEY_COMMIT_BASE);
request = getGetRequest(fileBaseUri);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_NOT_FOUND, response.getResponseCode());
assertEquals(gitDiffUri, jsonPart.getString(ProtocolConstants.KEY_LOCATION));
}
@Test
public void testDiffWithCommonAncestor() throws Exception {
// clone: create
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
String workspaceId = workspaceIdFromLocation(workspaceLocation);
JSONObject project = createProjectOrLink(workspaceLocation, getMethodName().concat("Project"), null);
IPath clonePath = getClonePath(workspaceId, project);
JSONObject clone = clone(clonePath);
String cloneLocation = clone.getString(ProtocolConstants.KEY_LOCATION);
String branchesLocation = clone.getString(GitConstants.KEY_BRANCH);
// get project metadata
WebRequest request = getGetRequest(project.getString(ProtocolConstants.KEY_CONTENT_LOCATION));
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
project = new JSONObject(response.getText());
String branchName = "dev";
response = branch(branchesLocation, branchName);
assertEquals(branchName, new JSONObject(response.getText()).getString(ProtocolConstants.KEY_NAME));
checkoutBranch(cloneLocation, branchName);
// modify while on 'dev'
JSONObject testTxt = getChild(project, "test.txt");
modifyFile(testTxt, "change in dev");
JSONObject gitSection = project.getJSONObject(GitConstants.KEY_GIT);
String gitIndexUri = gitSection.getString(GitConstants.KEY_INDEX);
String gitStatusUri = gitSection.getString(GitConstants.KEY_STATUS);
String gitHeadUri = gitSection.getString(GitConstants.KEY_HEAD);
// "git add ."
request = GitAddTest.getPutGitIndexRequest(gitIndexUri);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// commit all
request = GitCommitTest.getPostGitCommitRequest(gitHeadUri, "commit on dev", false);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// assert clean
assertStatus(StatusResult.CLEAN, gitStatusUri);
// checkout 'master'
checkoutBranch(cloneLocation, Constants.MASTER);
// modify the same file on master
request = getPutFileRequest(clonePath.append("test.txt").toString(), "change in master");
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
gitSection = project.getJSONObject(GitConstants.KEY_GIT);
gitIndexUri = gitSection.getString(GitConstants.KEY_INDEX);
gitStatusUri = gitSection.getString(GitConstants.KEY_STATUS);
gitHeadUri = gitSection.getString(GitConstants.KEY_HEAD);
// "git add ."
request = GitAddTest.getPutGitIndexRequest(gitIndexUri);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// commit all
request = GitCommitTest.getPostGitCommitRequest(gitHeadUri, "commit on master", false);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// assert clean
assertStatus(StatusResult.CLEAN, gitStatusUri);
String masterDiffLocation = findDiffLocationForBranchByName(branchesLocation, Constants.MASTER);
String location = getDiffLocation(masterDiffLocation, branchName);
// TODO: don't create URIs out of thin air
location += "test.txt";
request = getGetRequest(location + "?parts=uris,diff");
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
String[] parts = parseMultiPartResponse(response);
assertDiffUris(location, new String[] {"change in master", "change in dev", "test"}, new JSONObject(parts[0]));
}
@Test
public void testDiffForBranches() throws Exception {
// clone
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
String workspaceId = workspaceIdFromLocation(workspaceLocation);
JSONObject project = createProjectOrLink(workspaceLocation, getMethodName().concat("Project"), null);
IPath clonePath = getClonePath(workspaceId, project);
JSONObject clone = clone(clonePath);
String branchesLocation = clone.getString(GitConstants.KEY_BRANCH);
String remotesLocation = clone.getString(GitConstants.KEY_REMOTE);
// get project metadata
WebRequest request = getGetRequest(project.getString(ProtocolConstants.KEY_CONTENT_LOCATION));
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
project = new JSONObject(response.getText());
// modify file on master
JSONObject testTxt = getChild(project, "test.txt");
modifyFile(testTxt, "change in master");
addFile(testTxt);
commitFile(testTxt, "commit in master", false);
String masterDiffLocation = findDiffLocationForBranchByName(branchesLocation, Constants.MASTER);
JSONObject originMasterRemoteBranch = getRemoteBranch(remotesLocation, 1, 0, Constants.MASTER);
// compare master vs origin/master
String diffLocation = getDiffLocation(masterDiffLocation, originMasterRemoteBranch.getString(ProtocolConstants.KEY_NAME));
String[] parts = getDiff(diffLocation);
StringBuilder sb = new StringBuilder();
sb.append("diff --git a/test.txt b/test.txt").append("\n");
sb.append("index 597c638..30d74d2 100644").append("\n");
sb.append("--- a/test.txt").append("\n");
sb.append("+++ b/test.txt").append("\n");
sb.append("@@ -1 +1 @@").append("\n");
sb.append("-change in master").append("\n");
sb.append("\\ No newline at end of file").append("\n");
sb.append("+test").append("\n");
sb.append("\\ No newline at end of file").append("\n");
assertEquals(sb.toString(), parts[1]);
// compare origin/master vs master
diffLocation = getDiffLocation(originMasterRemoteBranch.getString(GitConstants.KEY_DIFF), Constants.MASTER);
parts = getDiff(diffLocation);
sb.setLength(0);
sb.append("diff --git a/test.txt b/test.txt").append("\n");
sb.append("index 30d74d2..597c638 100644").append("\n");
sb.append("--- a/test.txt").append("\n");
sb.append("+++ b/test.txt").append("\n");
sb.append("@@ -1 +1 @@").append("\n");
sb.append("-test").append("\n");
sb.append("\\ No newline at end of file").append("\n");
sb.append("+change in master").append("\n");
sb.append("\\ No newline at end of file").append("\n");
assertEquals(sb.toString(), parts[1]);
}
private String findDiffLocationForBranchByName(String gitBranchUri, String branchName) throws IOException, SAXException, JSONException {
JSONObject branches = listBranches(gitBranchUri);
JSONArray branchesArray = branches.getJSONArray(ProtocolConstants.KEY_CHILDREN);
for (int i = 0; i < branchesArray.length(); i++) {
if (branchesArray.getJSONObject(i).getString(ProtocolConstants.KEY_NAME).equals(branchName))
return branchesArray.getJSONObject(i).getString(GitConstants.KEY_DIFF);
}
fail(NLS.bind("Could not find branch: {0}", branchName));
return null;
}
private void assertDiffUris(String expectedLocation, String[] expectedContent, JSONObject jsonPart) throws JSONException, IOException, SAXException {
assertEquals(Diff.TYPE, jsonPart.getString(ProtocolConstants.KEY_TYPE));
String fileOldUri = jsonPart.getString(GitConstants.KEY_COMMIT_OLD);
WebRequest request = getGetRequest(fileOldUri);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
assertEquals(expectedContent[0], response.getText());
String fileNewUri = jsonPart.getString(GitConstants.KEY_COMMIT_NEW);
request = getGetRequest(fileNewUri);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
assertEquals(expectedContent[1], response.getText());
String fileBaseUri = jsonPart.getString(GitConstants.KEY_COMMIT_BASE);
request = getGetRequest(fileBaseUri);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
assertEquals(expectedContent[2], response.getText());
assertEquals(expectedLocation, jsonPart.getString(ProtocolConstants.KEY_LOCATION));
}
static String[] getDiff(String location) throws IOException, SAXException {
WebRequest request = getGetGitDiffRequest(location, new String[] {});
WebConversation conversation = new WebConversation();
conversation.setExceptionsThrownOnErrorStatus(false);
WebResponse response = conversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
return parseMultiPartResponse(response);
}
/**
* Creates a request to get the diff result for the given location.
* @param location Either an absolute URI, or a workspace-relative URI
* @param paths an array containing paths to be included in the diff, can be empty
*/
static WebRequest getGetGitDiffRequest(String location, String[] paths) {
String requestURI = toAbsoluteURI(location);
for (String path : paths) {
requestURI = addParam(requestURI, "Path=" + path);
}
WebRequest request = new GetMethodWebRequest(requestURI);
request.setHeaderField(ProtocolConstants.HEADER_ORION_VERSION, "1");
setAuthentication(request);
return request;
}
private static String addParam(String location, String param) {
location += location.indexOf("?") != -1 ? "&" : "?";
location += param;
return location;
}
private String getDiffLocation(String oldCommitDiffLocation, String newCommitName) throws JSONException, IOException, SAXException {
assertDiffUri(oldCommitDiffLocation);
WebRequest request = getPostGitDiffRequest(oldCommitDiffLocation, newCommitName);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
String location = response.getHeaderField(ProtocolConstants.HEADER_LOCATION);
assertEquals(location, new JSONObject(response.getText()).getString(ProtocolConstants.KEY_LOCATION));
return location;
}
private JSONObject findCommitByMessage(String gitHeadUri, String commitMessage) throws IOException, SAXException, JSONException {
JSONArray commitsArray = log(gitHeadUri);
for (int i = 0; i < commitsArray.length(); i++) {
if (commitsArray.getJSONObject(i).getString(GitConstants.KEY_COMMIT_MESSAGE).equals(commitMessage))
return commitsArray.getJSONObject(i);
}
fail(NLS.bind("Commit with message '{0}' could not be found.", commitMessage));
return null;
}
private String getDiffCachedLocation(JSONObject fileObject) throws JSONException, IOException, SAXException {
// cannot get status on a file
// request the status on parent
String fileLocation = fileObject.getString(ProtocolConstants.KEY_LOCATION);
WebRequest request = getGetRequest(fileLocation + "?parts=meta");
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject fileMetaObject = new JSONObject(response.getText());
JSONArray parents = fileMetaObject.getJSONArray(ProtocolConstants.KEY_PARENTS);
JSONObject parentObject = parents.getJSONObject(0);
request = getGetRequest(parentObject.getString(ProtocolConstants.KEY_LOCATION));
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
parentObject = new JSONObject(response.getText());
request = getGetGitStatusRequest(parentObject.getJSONObject(GitConstants.KEY_GIT).getString(GitConstants.KEY_STATUS));
response = webConversation.getResponse(request);
assertTrue(HttpURLConnection.HTTP_OK == response.getResponseCode() || HttpURLConnection.HTTP_ACCEPTED == response.getResponseCode());
ServerStatus status = waitForTask(response);
assertTrue(status.toString(), status.isOK());
JSONObject statusResponse = status.getJsonData();
// find entry for the file
JSONArray changed = statusResponse.getJSONArray(GitConstants.KEY_STATUS_CHANGED);
for (int i = 0; i < changed.length(); i++) {
JSONObject changedEntry = changed.getJSONObject(i);
if (changedEntry.getString(ProtocolConstants.KEY_NAME).equals(fileObject.getString(ProtocolConstants.KEY_NAME))) {
return changedEntry.getJSONObject(GitConstants.KEY_GIT).getString(GitConstants.KEY_DIFF);
}
}
fail(NLS.bind("Diff Cached Location for {0}, could not be found", fileObject.getString(ProtocolConstants.KEY_NAME)));
return null;
}
private static WebRequest getPostGitDiffRequest(String location, String str) throws JSONException, UnsupportedEncodingException {
String requestURI = toAbsoluteURI(location);
JSONObject body = new JSONObject();
body.put(GitConstants.KEY_COMMIT_NEW, str);
str = body.toString();
WebRequest request = new PostMethodWebRequest(requestURI, IOUtilities.toInputStream(str), "UTF-8");
request.setHeaderField(ProtocolConstants.HEADER_ORION_VERSION, "1");
setAuthentication(request);
return request;
}
static String[] parseMultiPartResponse(WebResponse response) throws IOException {
String typeHeader = response.getHeaderField(ProtocolConstants.HEADER_CONTENT_TYPE);
String boundary = typeHeader.substring(typeHeader.indexOf("boundary=\"") + 10, typeHeader.length() - 1); //$NON-NLS-1$
BufferedReader reader = new BufferedReader(new StringReader(response.getText()));
StringBuilder buf = new StringBuilder();
List<String> parts = new ArrayList<String>();
try {
String line;
while ((line = reader.readLine()) != null) {
if (line.equals("--" + boundary)) {
line = reader.readLine(); // Content-Type:{...}
if (buf.length() > 0) {
parts.add(buf.toString());
buf.setLength(0);
}
} else {
if (buf.length() > 0)
buf.append("\n");
buf.append(line);
}
}
} finally {
IOUtilities.safeClose(reader);
}
parts.add(buf.toString());
assertEquals(2, parts.size());
// JSON
assertTrue(parts.get(0).startsWith("{"));
// diff or empty when there is no difference
assertTrue(parts.get(1).length() == 0 || parts.get(1).startsWith("diff"));
return parts.toArray(new String[0]);
}
private static void assertDiffUri(String diffUri) {
URI uri = URI.create(toRelativeURI(diffUri));
IPath path = new Path(uri.getPath());
// /gitapi/diff/{scope}/file/{filePath}
assertTrue(path.segmentCount() > 4);
assertEquals(GitServlet.GIT_URI.substring(1), path.segment(0));
assertEquals(Diff.RESOURCE, path.segment(1));
assertTrue("file".equals(path.segment(3)));
}
}