/*******************************************************************************
* 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.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import org.eclipse.core.runtime.IPath;
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.git.GitConstants;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Ignore;
import org.junit.Test;
import com.meterware.httpunit.GetMethodWebRequest;
import com.meterware.httpunit.PostMethodWebRequest;
import com.meterware.httpunit.WebRequest;
import com.meterware.httpunit.WebResponse;
public class GitCommitTest extends GitTest {
@Test
public void testCommitOnly() 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 gitStatusUri = gitSection.getString(GitConstants.KEY_STATUS);
JSONObject testTxt = getChild(project, "test.txt");
modifyFile(testTxt, "change to commit");
addFile(testTxt);
JSONObject folder1 = getChild(project, "folder");
JSONObject folderTxt = getChild(folder1, "folder.txt");
modifyFile(folderTxt, "change to commit");
addFile(folderTxt);
assertStatus(new StatusResult().setChanged(2), gitStatusUri);
// "git commit -m 'message' -- test.txt
final String commitMessage = "message";
JSONObject commit = commitFile(testTxt, commitMessage);
// check if response contains most important parts and if commit
// message is valid
assertNotNull(commit.optString(ProtocolConstants.KEY_LOCATION, null));
assertNotNull(commit.optString(ProtocolConstants.KEY_NAME, null));
assertEquals(commitMessage, commit.getString(GitConstants.KEY_COMMIT_MESSAGE));
// still in index, not committed
assertStatus(new StatusResult().setChangedNames("folder/folder.txt"), gitStatusUri);
}
@Test
public void testCommitNoComment() 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 to commit");
JSONObject gitSection = project.getJSONObject(GitConstants.KEY_GIT);
String gitHeadUri = gitSection.getString(GitConstants.KEY_HEAD);
addFile(testTxt);
// commit with a null message
WebRequest request = getPostGitCommitRequest(gitHeadUri /* all */, null, false);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_BAD_REQUEST, response.getResponseCode());
}
@Test
public void testCommitEmptyComment() 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 to commit");
JSONObject gitSection = project.getJSONObject(GitConstants.KEY_GIT);
String gitHeadUri = gitSection.getString(GitConstants.KEY_HEAD);
addFile(testTxt);
// commit with a null message
WebRequest request = getPostGitCommitRequest(gitHeadUri /* all */, "", false);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_BAD_REQUEST, response.getResponseCode());
}
@Test
public void testCommitAll() 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 to commit");
JSONObject folder1 = getChild(project, "folder");
JSONObject folderTxt = getChild(folder1, "folder.txt");
modifyFile(folderTxt, "change to commit");
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 ."
WebRequest request = GitAddTest.getPutGitIndexRequest(gitIndexUri);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
assertStatus(new StatusResult().setChanged(2), gitStatusUri);
// commit all
request = getPostGitCommitRequest(gitHeadUri, "message", false);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// assert clean
assertStatus(StatusResult.CLEAN, gitStatusUri);
}
@Test
public void testCommitAmend() 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 to commit");
JSONObject gitSection = project.getJSONObject(GitConstants.KEY_GIT);
String gitIndexUri = gitSection.getString(GitConstants.KEY_INDEX);
String gitHeadUri = gitSection.getString(GitConstants.KEY_HEAD);
// "git add ."
WebRequest request = GitAddTest.getPutGitIndexRequest(gitIndexUri);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// commit all
request = getPostGitCommitRequest(gitHeadUri, "Comit massage", false); // typos
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// amend last commit
request = getPostGitCommitRequest(gitHeadUri, "Commit message", true);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONArray commitsArray = log(gitHeadUri);
assertEquals(2, commitsArray.length());
JSONObject commit = commitsArray.getJSONObject(0);
assertEquals("Commit message", commit.get(GitConstants.KEY_COMMIT_MESSAGE));
commit = commitsArray.getJSONObject(1);
assertEquals("Initial commit", commit.get(GitConstants.KEY_COMMIT_MESSAGE));
}
@Test
public void testCommitHeadContent() 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, "in HEAD");
JSONObject gitSection = project.getJSONObject(GitConstants.KEY_GIT);
String gitHeadUri = gitSection.getString(GitConstants.KEY_HEAD);
addFile(testTxt);
// commit all
WebRequest request = getPostGitCommitRequest(gitHeadUri, "message", false);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject testTxtGitSection = testTxt.getJSONObject(GitConstants.KEY_GIT);
String testTxtGitHeadUri = testTxtGitSection.getString(GitConstants.KEY_HEAD);
request = getGetGitCommitRequest(testTxtGitHeadUri, true);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
assertEquals("in HEAD", response.getText());
}
@Test
@Ignore("not yet implemented")
public void testCommitContentBySha() {
// TODO: implement
}
@Test
public void testCommitAllInFolder() throws Exception {
// see bug 349480
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
IPath[] clonePaths = createTestProjects(workspaceLocation);
for (IPath clonePath : clonePaths) {
// clone a repo
String contentLocation = clone(clonePath).getString(ProtocolConstants.KEY_CONTENT_LOCATION);
// get project metadata
WebRequest request = getGetRequest(contentLocation);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject cloneFolder = new JSONObject(response.getText());
String fileName = "folder2.txt";
JSONObject folder = getChild(cloneFolder, "folder");
request = getPostFilesRequest(folder.getString(ProtocolConstants.KEY_LOCATION), getNewFileJSON(fileName).toString(), fileName);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_CREATED, response.getResponseCode());
JSONObject testTxt = getChild(cloneFolder, "test.txt");
// drill down to 'folder'
JSONObject folderGitSection = folder.getJSONObject(GitConstants.KEY_GIT);
String folderGitStatusUri = folderGitSection.getString(GitConstants.KEY_STATUS);
JSONObject folder2Txt = getChild(folder, "folder2.txt");
JSONObject folderTxt = getChild(folder, "folder.txt");
// git section for the new file
JSONObject folder2TxtGitSection = folder2Txt.getJSONObject(GitConstants.KEY_GIT);
String folder2TxtGitIndexUri = folder2TxtGitSection.getString(GitConstants.KEY_INDEX);
String folder2TxtGitHeadUri = folder2TxtGitSection.getString(GitConstants.KEY_HEAD);
// stage the new file
request = GitAddTest.getPutGitIndexRequest(folder2TxtGitIndexUri);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// commit the new file
request = getPostGitCommitRequest(folder2TxtGitHeadUri, "folder/folder2.txt added", false);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// check status - clean
assertStatus(StatusResult.CLEAN, folderGitStatusUri);
// modify all
modifyFile(testTxt, "change");
modifyFile(folderTxt, "change");
modifyFile(folder2Txt, "change");
// check status - modified=3
assertStatus(new StatusResult().setModified(3), folderGitStatusUri);
addFile(folderTxt);
addFile(testTxt);
// check status - modified=1, changed=2
assertStatus(new StatusResult().setModified(1).setChanged(2), folderGitStatusUri);
// commit all
// XXX: using HEAD URI for folder will commit all files in the folder, regardless of index state
// request = getPostGitCommitRequest(folderGitHeadUri, "test.txt and folder/folder.txt changed", false);
// the UI should use HEAD URI for the clone/root to commit all staged files
JSONObject clone = getCloneForGitResource(folder);
String cloneFolderGitHeadUri = clone.getString(GitConstants.KEY_HEAD);
request = getPostGitCommitRequest(cloneFolderGitHeadUri, "test.txt and folder/folder.txt changed", false);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// check status - changed=1
assertStatus(new StatusResult().setModifiedNames("folder/folder2.txt"), folderGitStatusUri);
// check the last commit for the repo
JSONArray commitsArray = log(cloneFolderGitHeadUri);
assertEquals(3, commitsArray.length());
JSONObject commit = commitsArray.getJSONObject(0);
assertEquals("test.txt and folder/folder.txt changed", commit.get(GitConstants.KEY_COMMIT_MESSAGE));
JSONObject diffsParent = commit.getJSONObject(GitConstants.KEY_COMMIT_DIFFS);
JSONArray diffs = diffsParent.getJSONArray(ProtocolConstants.KEY_CHILDREN);
assertEquals(2, diffs.length());
String oldPath = diffs.getJSONObject(0).getString(GitConstants.KEY_COMMIT_DIFF_OLDPATH);
assertTrue("folder/folder.txt".equals(oldPath) || "test.txt".equals(oldPath));
oldPath = diffs.getJSONObject(1).getString(GitConstants.KEY_COMMIT_DIFF_OLDPATH);
assertTrue("folder/folder.txt".equals(oldPath) || "test.txt".equals(oldPath));
}
}
@Test
public void testCommitWithCommiterOverwritten() throws Exception {
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
IPath[] clonePaths = createTestProjects(workspaceLocation);
for (IPath clonePath : clonePaths) {
// clone a repo
String contentLocation = clone(clonePath).getString(ProtocolConstants.KEY_CONTENT_LOCATION);
// get project metadata
WebRequest request = getGetRequest(contentLocation);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject project = new JSONObject(response.getText());
JSONObject gitSection = project.getJSONObject(GitConstants.KEY_GIT);
String gitHeadUri = gitSection.getString(GitConstants.KEY_HEAD);
String gitIndexUri = gitSection.getString(GitConstants.KEY_INDEX);
// "git add ."
request = GitAddTest.getPutGitIndexRequest(gitIndexUri);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// commit all
final String commiterName = "committer name";
final String commiterEmail = "committer email";
request = getPostGitCommitRequest(gitHeadUri, "Comit message", false, commiterName, commiterEmail, null, null);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// log
JSONArray commitsArray = log(gitHeadUri);
assertEquals(2, commitsArray.length());
JSONObject commit = commitsArray.getJSONObject(0);
assertEquals(commiterName, commit.get(GitConstants.KEY_COMMITTER_NAME));
assertEquals(commiterEmail, commit.get(GitConstants.KEY_COMMITTER_EMAIL));
}
}
@Test
public void testCommitWithAuthorOverwritten() throws Exception {
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
IPath[] clonePaths = createTestProjects(workspaceLocation);
for (IPath clonePath : clonePaths) {
// clone a repo
String contentLocation = clone(clonePath).getString(ProtocolConstants.KEY_CONTENT_LOCATION);
// get project metadata
WebRequest request = getGetRequest(contentLocation);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject project = new JSONObject(response.getText());
JSONObject gitSection = project.getJSONObject(GitConstants.KEY_GIT);
String gitHeadUri = gitSection.getString(GitConstants.KEY_HEAD);
String gitIndexUri = gitSection.getString(GitConstants.KEY_INDEX);
// "git add ."
request = GitAddTest.getPutGitIndexRequest(gitIndexUri);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// commit all
final String commiterName = "committer name";
final String commiterEmail = "committer email";
request = getPostGitCommitRequest(gitHeadUri, "Comit message", false, commiterName, commiterEmail, null, null);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// log
JSONArray commitsArray = log(gitHeadUri);
assertEquals(2, commitsArray.length());
JSONObject commit = commitsArray.getJSONObject(0);
assertEquals(commiterName, commit.get(GitConstants.KEY_COMMITTER_NAME));
assertEquals(commiterEmail, commit.get(GitConstants.KEY_COMMITTER_EMAIL));
}
}
@Test
public void testCommitterAndAuthorFallback() throws Exception {
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
IPath[] clonePaths = createTestProjects(workspaceLocation);
for (IPath clonePath : clonePaths) {
// clone a repo
String contentLocation = clone(clonePath).getString(ProtocolConstants.KEY_CONTENT_LOCATION);
// get project metadata
WebRequest request = getGetRequest(contentLocation);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject project = new JSONObject(response.getText());
JSONObject gitSection = project.getJSONObject(GitConstants.KEY_GIT);
String gitHeadUri = gitSection.getString(GitConstants.KEY_HEAD);
String gitIndexUri = gitSection.getString(GitConstants.KEY_INDEX);
String gitConfigUri = gitSection.getString(GitConstants.KEY_CONFIG);
// set user.name and user.email
final String name = "name";
final String email = "email";
final String defaultName = "default name";
final String defaultEmail = "default email";
request = GitConfigTest.getPostGitConfigRequest(gitConfigUri, "user.name", defaultName);
response = webConversation.getResponse(request);
assertEquals(response.getText(), HttpURLConnection.HTTP_CREATED, response.getResponseCode());
request = GitConfigTest.getPostGitConfigRequest(gitConfigUri, "user.email", defaultEmail);
response = webConversation.getResponse(request);
assertEquals(response.getText(), HttpURLConnection.HTTP_CREATED, response.getResponseCode());
// "git add ."
request = GitAddTest.getPutGitIndexRequest(gitIndexUri);
response = webConversation.getResponse(request);
assertEquals(response.getText(), HttpURLConnection.HTTP_OK, response.getResponseCode());
// commit - author and committer not specified
request = getPostGitCommitRequest(gitHeadUri, "1", false, null, null, null, null);
response = webConversation.getResponse(request);
assertEquals(response.getText(), HttpURLConnection.HTTP_OK, response.getResponseCode());
// log - expect default values
JSONArray commitsArray = log(gitHeadUri);
assertEquals(2, commitsArray.length());
JSONObject commit = commitsArray.getJSONObject(0);
assertEquals(defaultName, commit.get(GitConstants.KEY_COMMITTER_NAME));
assertEquals(defaultEmail, commit.get(GitConstants.KEY_COMMITTER_EMAIL));
assertEquals(defaultName, commit.get(GitConstants.KEY_AUTHOR_NAME));
assertEquals(defaultEmail, commit.get(GitConstants.KEY_AUTHOR_EMAIL));
// commit - only committer given
request = getPostGitCommitRequest(gitHeadUri, "2", true, name, email, null, null);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// log - expect author is the same as committer
commitsArray = log(gitHeadUri);
assertEquals(2, commitsArray.length());
commit = commitsArray.getJSONObject(0);
assertEquals(name, commit.get(GitConstants.KEY_COMMITTER_NAME));
assertEquals(email, commit.get(GitConstants.KEY_COMMITTER_EMAIL));
assertEquals(name, commit.get(GitConstants.KEY_AUTHOR_NAME));
assertEquals(email, commit.get(GitConstants.KEY_AUTHOR_EMAIL));
// commit - only committer name given
request = getPostGitCommitRequest(gitHeadUri, "3", true, name, null, null, null);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// log - expect author is the same as committer and their email is defaultEmail
commitsArray = log(gitHeadUri);
assertEquals(2, commitsArray.length());
commit = commitsArray.getJSONObject(0);
assertEquals(name, commit.get(GitConstants.KEY_COMMITTER_NAME));
assertEquals(defaultEmail, commit.get(GitConstants.KEY_COMMITTER_EMAIL));
assertEquals(name, commit.get(GitConstants.KEY_AUTHOR_NAME));
assertEquals(defaultEmail, commit.get(GitConstants.KEY_AUTHOR_EMAIL));
}
}
static WebRequest getPostGitCommitRequest(String location, String message, boolean amend, String committerName, String committerEmail, String authorName, String authorEmail) throws JSONException, UnsupportedEncodingException {
String requestURI = toAbsoluteURI(location);
JSONObject body = new JSONObject();
body.put(GitConstants.KEY_COMMIT_MESSAGE, message);
body.put(GitConstants.KEY_COMMIT_AMEND, Boolean.toString(amend));
body.put(GitConstants.KEY_COMMITTER_NAME, committerName);
body.put(GitConstants.KEY_COMMITTER_EMAIL, committerEmail);
body.put(GitConstants.KEY_AUTHOR_NAME, authorName);
body.put(GitConstants.KEY_AUTHOR_EMAIL, authorEmail);
WebRequest request = new PostMethodWebRequest(requestURI, IOUtilities.toInputStream(body.toString()), "UTF-8");
request.setHeaderField(ProtocolConstants.HEADER_ORION_VERSION, "1");
setAuthentication(request);
return request;
}
static WebRequest getPostGitCommitRequest(String location, String message, boolean amend) throws JSONException, UnsupportedEncodingException {
return getPostGitCommitRequest(location, message, amend, null, null, null, null);
}
static WebRequest getGetGitCommitRequest(String location, boolean body) {
return getGetGitCommitRequest(location, body, null, null);
}
static WebRequest getGetGitCommitRequest(String location, boolean body, Integer page, Integer pageSize) {
String requestURI = toAbsoluteURI(location);
boolean firstParam = true;
if (body) {
if (firstParam) {
requestURI += "?";
firstParam = false;
} else {
requestURI += "&";
}
requestURI += "parts=body";
}
if (page != null) {
if (firstParam) {
requestURI += "?";
firstParam = false;
} else {
requestURI += "&";
}
requestURI += "page=" + page.intValue();
}
if (pageSize != null) {
if (firstParam) {
requestURI += "?";
firstParam = false;
} else {
requestURI += "&";
}
requestURI += "pageSize=" + pageSize.intValue();
}
WebRequest request = new GetMethodWebRequest(requestURI);
request.setHeaderField(ProtocolConstants.HEADER_ORION_VERSION, "1");
setAuthentication(request);
return request;
}
}