/*******************************************************************************
* 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.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.MergeResult.MergeStatus;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.transport.RemoteRefUpdate.Status;
import org.eclipse.jgit.transport.URIish;
import org.eclipse.jgit.util.FileUtils;
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.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.Test;
import com.meterware.httpunit.PostMethodWebRequest;
import com.meterware.httpunit.WebRequest;
import com.meterware.httpunit.WebResponse;
public class GitPushTest extends GitTest {
@BeforeClass
public static void prepareSsh() {
readSshProperties();
}
@Test
public void testPushNoBody() throws Exception {
// clone a repo
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
String workspaceId = workspaceIdFromLocation(workspaceLocation);
JSONObject project = createProjectOrLink(workspaceLocation, getMethodName().concat("Project"), null);
IPath clonePath = getClonePath(workspaceId, project);
clone(clonePath);
// 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());
JSONObject gitSection = project.getJSONObject(GitConstants.KEY_GIT);
String gitRemoteUri = gitSection.getString(GitConstants.KEY_REMOTE);
// get remote branch location
JSONObject remoteBranch = getRemoteBranch(gitRemoteUri, 1, 0, Constants.MASTER);
String remoteBranchLocation = remoteBranch.getString(ProtocolConstants.KEY_LOCATION);
// push with no body
request = getPostGitRemoteRequest(remoteBranchLocation, null, false, false);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_BAD_REQUEST, response.getResponseCode());
}
@Test
public void testPushHead() throws Exception {
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
String workspaceId = workspaceIdFromLocation(workspaceLocation);
// clone1
JSONObject project1 = createProjectOrLink(workspaceLocation, getMethodName().concat("Project1"), null);
IPath clonePath1 = getClonePath(workspaceId, project1);
clone(clonePath1);
// get project1 metadata
WebRequest request = getGetRequest(project1.getString(ProtocolConstants.KEY_CONTENT_LOCATION));
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
project1 = new JSONObject(response.getText());
JSONObject gitSection1 = project1.getJSONObject(GitConstants.KEY_GIT);
String gitRemoteUri1 = gitSection1.getString(GitConstants.KEY_REMOTE);
String gitHeadUri1 = gitSection1.getString(GitConstants.KEY_HEAD);
// clone2
JSONObject project2 = createProjectOrLink(workspaceLocation, getMethodName().concat("Project2"), null);
IPath clonePath2 = getClonePath(workspaceId, project2);
clone(clonePath2);
// get project2 metadata
request = getGetRequest(project2.getString(ProtocolConstants.KEY_CONTENT_LOCATION));
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
project2 = new JSONObject(response.getText());
JSONObject gitSection2 = project2.getJSONObject(GitConstants.KEY_GIT);
String gitRemoteUri2 = gitSection2.getString(GitConstants.KEY_REMOTE);
String gitHeadUri2 = gitSection2.getString(GitConstants.KEY_HEAD);
// clone1: list remotes
request = GitRemoteTest.getGetGitRemoteRequest(gitRemoteUri1);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject remotes = new JSONObject(response.getText());
JSONArray remotesArray = remotes.getJSONArray(ProtocolConstants.KEY_CHILDREN);
assertEquals(1, remotesArray.length());
JSONObject remote = remotesArray.getJSONObject(0);
assertNotNull(remote);
assertEquals(Constants.DEFAULT_REMOTE_NAME, remote.getString(ProtocolConstants.KEY_NAME));
// clone1: change
JSONObject testTxt1 = getChild(project1, "test.txt");
modifyFile(testTxt1, "incoming change");
addFile(testTxt1);
// clone1: commit
request = GitCommitTest.getPostGitCommitRequest(gitHeadUri1, "incoming change commit", false);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// clone1: push
ServerStatus pushStatus = push(gitRemoteUri1, 1, 0, Constants.MASTER, Constants.HEAD, false);
assertEquals(true, pushStatus.isOK());
// clone2: get remote branch location
JSONObject remoteBranch = getRemoteBranch(gitRemoteUri2, 1, 0, Constants.MASTER);
String remoteBranchLocation2 = remoteBranch.getString(ProtocolConstants.KEY_LOCATION);
// clone2: fetch
fetch(remoteBranchLocation2);
// clone2: get remote details
JSONObject remoteBranch2 = getRemoteBranch(gitRemoteUri2, 1, 0, Constants.MASTER);
String newRefId2 = remoteBranch2.getString(ProtocolConstants.KEY_ID);
// clone2: merge into HEAD, "git merge origin/master"
gitHeadUri2 = remoteBranch2.getString(GitConstants.KEY_HEAD);
JSONObject merge = merge(gitHeadUri2, newRefId2);
MergeStatus mergeResult = MergeStatus.valueOf(merge.getString(GitConstants.KEY_RESULT));
assertEquals(MergeStatus.FAST_FORWARD, mergeResult);
// clone2: assert change from clone1 is in place
JSONObject testTxt2 = getChild(project2, "test.txt");
request = getGetRequest(testTxt2.getString(ProtocolConstants.KEY_LOCATION));
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
assertEquals("incoming change", response.getText());
}
@Test
public void testPushHeadSshWithPrivateKeyPassphrase() throws Exception {
Assume.assumeTrue(sshRepo2 != null);
Assume.assumeTrue(knownHosts2 != null);
Assume.assumeTrue(privateKey != null);
Assume.assumeTrue(passphrase != null);
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
String workspaceId = workspaceIdFromLocation(workspaceLocation);
URIish uri = new URIish(sshRepo2);
// clone1: create
JSONObject project1 = createProjectOrLink(workspaceLocation, getMethodName().concat("Project1"), null);
IPath clonePath = getClonePath(workspaceId, project1);
WebRequest request = new PostGitCloneRequest().setURIish(uri).setFilePath(clonePath).setKnownHosts(knownHosts2).setPrivateKey(privateKey).setPublicKey(publicKey).setPassphrase(passphrase).getWebRequest();
String cloneContentLocation1 = clone(request);
// clone1: get project/folder metadata
request = getGetRequest(cloneContentLocation1);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
project1 = new JSONObject(response.getText());
// clone1: get git links
JSONObject gitSection1 = project1.getJSONObject(GitConstants.KEY_GIT);
String gitRemoteUri1 = gitSection1.optString(GitConstants.KEY_REMOTE);
String gitIndexUri1 = gitSection1.optString(GitConstants.KEY_INDEX);
String gitHeadUri1 = gitSection1.optString(GitConstants.KEY_HEAD);
// clone2: create
JSONObject project2 = createProjectOrLink(workspaceLocation, getMethodName().concat("Project2"), null);
clonePath = getClonePath(workspaceId, project2);
request = new PostGitCloneRequest().setURIish(uri).setFilePath(clonePath).setKnownHosts(knownHosts2).setPrivateKey(privateKey).setPublicKey(publicKey).setPassphrase(passphrase).getWebRequest();
String cloneContentLocation2 = clone(request);
// clone2: get project/folder metadata
request = getGetRequest(cloneContentLocation2);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
project2 = new JSONObject(response.getText());
// clone2: get git links
JSONObject gitSection2 = project2.getJSONObject(GitConstants.KEY_GIT);
String gitRemoteUri2 = gitSection2.getString(GitConstants.KEY_REMOTE);
String gitCommitUri2 = gitSection2.getString(GitConstants.KEY_COMMIT);
// clone1: list remotes
request = GitRemoteTest.getGetGitRemoteRequest(gitRemoteUri1);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject remotes = new JSONObject(response.getText());
JSONArray remotesArray = remotes.getJSONArray(ProtocolConstants.KEY_CHILDREN);
assertEquals(1, remotesArray.length());
JSONObject remote = remotesArray.getJSONObject(0);
assertNotNull(remote);
assertEquals(Constants.DEFAULT_REMOTE_NAME, remote.getString(ProtocolConstants.KEY_NAME));
// clone1: change
JSONObject testTxt1 = getChild(project1, "test.txt");
modifyFile(testTxt1, "incoming change");
// clone1: add
request = GitAddTest.getPutGitIndexRequest(gitIndexUri1);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// clone1: commit
request = GitCommitTest.getPostGitCommitRequest(gitHeadUri1, "incoming change commit", false);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// clone1: push
ServerStatus pushStatus = push(gitRemoteUri1, 1, 0, Constants.MASTER, Constants.HEAD, false, null, knownHosts2, privateKey, publicKey, passphrase, true);
assertEquals(true, pushStatus.isOK());
// clone2: get remote branch location
JSONObject remoteBranch = getRemoteBranch(gitRemoteUri2, 1, 0, Constants.MASTER);
String remoteBranchLocation2 = remoteBranch.getString(ProtocolConstants.KEY_LOCATION);
// clone2: fetch
fetch(remoteBranchLocation2, null, knownHosts2, privateKey, publicKey, passphrase, true);
// clone2: get remote details
JSONObject remoteBranch2 = getRemoteBranch(gitRemoteUri2, 1, 0, Constants.MASTER);
String newRefId2 = remoteBranch2.getString(ProtocolConstants.KEY_ID);
// clone2: merge into HEAD, "git merge origin/master"
gitCommitUri2 = remoteBranch2.getString(GitConstants.KEY_HEAD);
JSONObject merge = merge(gitCommitUri2, newRefId2);
MergeStatus mergeResult = MergeStatus.valueOf(merge.getString(GitConstants.KEY_RESULT));
assertEquals(MergeStatus.FAST_FORWARD, mergeResult);
// clone2: assert change from clone1 is in place
JSONObject testTxt2 = getChild(project2, "test.txt");
request = getGetRequest(testTxt2.getString(ProtocolConstants.KEY_LOCATION));
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
assertEquals("incoming change", response.getText());
}
@Test
public void testPushBranch() throws Exception {
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
String workspaceId = workspaceIdFromLocation(workspaceLocation);
// clone1: create
JSONObject project1 = createProjectOrLink(workspaceLocation, getMethodName().concat("Project1"), null);
IPath clonePath1 = getClonePath(workspaceId, project1);
JSONObject clone1 = clone(clonePath1);
String cloneLocation1 = clone1.getString(ProtocolConstants.KEY_LOCATION);
String branchesLocation1 = clone1.getString(GitConstants.KEY_BRANCH);
// get project1 metadata
WebRequest request = getGetRequest(project1.getString(ProtocolConstants.KEY_CONTENT_LOCATION));
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
project1 = new JSONObject(response.getText());
JSONObject gitSection1 = project1.optJSONObject(GitConstants.KEY_GIT);
assertNotNull(gitSection1);
String gitIndexUri1 = gitSection1.getString(GitConstants.KEY_INDEX);
String gitHeadUri1 = gitSection1.getString(GitConstants.KEY_HEAD);
// clone1: branch 'a'
response = branch(branchesLocation1, "a");
JSONObject branch = new JSONObject(response.getText());
checkoutBranch(cloneLocation1, "a");
// clone1: change
JSONObject testTxt1 = getChild(project1, "test.txt");
modifyFile(testTxt1, "branch 'a' change");
// clone1: add
request = GitAddTest.getPutGitIndexRequest(gitIndexUri1);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// clone1: commit
request = GitCommitTest.getPostGitCommitRequest(gitHeadUri1, "incoming branch 'a' commit", false);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// clone1: push by remote branch
JSONArray remoteBranchLocations = branch.getJSONArray(GitConstants.KEY_REMOTE);
assertEquals(1, remoteBranchLocations.length());
String remoteBranchLocation = remoteBranchLocations.getJSONObject(0).getJSONArray(ProtocolConstants.KEY_CHILDREN).getJSONObject(0).getString(ProtocolConstants.KEY_LOCATION);
ServerStatus pushStatus = push(remoteBranchLocation, Constants.HEAD, false);
assertTrue(pushStatus.isOK());
// clone1: get the remote branch name
request = getGetRequest(remoteBranchLocation);
response = webConversation.getResponse(request);
JSONObject remoteBranch1 = new JSONObject(response.getText());
String remoteBranchName1 = remoteBranch1.getString(ProtocolConstants.KEY_NAME);
// clone2
JSONObject project2 = createProjectOrLink(workspaceLocation, getMethodName().concat("Project2"), null);
IPath clonePath2 = getClonePath(workspaceId, project2);
JSONObject clone2 = clone(clonePath2);
String cloneLocation2 = clone2.getString(ProtocolConstants.KEY_LOCATION);
String branchesLocation2 = clone2.getString(GitConstants.KEY_BRANCH);
// get project2 metadata
request = getGetRequest(project2.getString(ProtocolConstants.KEY_CONTENT_LOCATION));
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
project2 = new JSONObject(response.getText());
JSONObject gitSection2 = project2.optJSONObject(GitConstants.KEY_GIT);
assertNotNull(gitSection2);
// create a local branch 'a' tracking remoteBranchName1 and checkout 'a'
response = branch(branchesLocation2, "a", remoteBranchName1);
assertEquals(HttpURLConnection.HTTP_CREATED, response.getResponseCode());
response = checkoutBranch(cloneLocation2, "a");
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject testTxt2 = getChild(project2, "test.txt");
request = getGetRequest(testTxt2.getString(ProtocolConstants.KEY_LOCATION));
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
assertEquals("branch 'a' change", response.getText());
}
@Test
public void testPushToDelete() throws Exception {
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
IPath[][] clonePaths = createTestClonePairs(workspaceLocation);
for (IPath[] clonePath : clonePaths) {
// clone 1
JSONObject clone1 = clone(clonePath[0]);
String cloneLocation1 = clone1.getString(ProtocolConstants.KEY_LOCATION);
String contentLocation1 = clone1.getString(ProtocolConstants.KEY_CONTENT_LOCATION);
String branchesLocation1 = clone1.getString(GitConstants.KEY_BRANCH);
// clone 1 - get project1 metadata
WebRequest request = getGetRequest(contentLocation1);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject project1 = new JSONObject(response.getText());
JSONObject gitSection1 = project1.getJSONObject(GitConstants.KEY_GIT);
String gitRemoteUri1 = gitSection1.getString(GitConstants.KEY_REMOTE);
String gitIndexUri1 = gitSection1.getString(GitConstants.KEY_INDEX);
String gitHeadUri1 = gitSection1.getString(GitConstants.KEY_HEAD);
// clone 1 - create branch "a"
response = branch(branchesLocation1, "a");
JSONObject newBranch = new JSONObject(response.getText());
JSONArray remoteBranchLocations1 = newBranch.getJSONArray(GitConstants.KEY_REMOTE);
assertEquals(1, remoteBranchLocations1.length());
// clone 1 - checkout "a"
final String newBranchName = "a";
response = checkoutBranch(cloneLocation1, newBranchName);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// clone 1 - change
JSONObject testTxt1 = getChild(project1, "test.txt");
modifyFile(testTxt1, "clone1 change");
// clone 1 - add
request = GitAddTest.getPutGitIndexRequest(gitIndexUri1);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// clone 1 - commit
request = GitCommitTest.getPostGitCommitRequest(gitHeadUri1, "clone1 change commit", false);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// clone 1 - push "a"
int i = 0;
String remoteBranchName = remoteBranchLocations1.getJSONObject(0).getJSONArray(ProtocolConstants.KEY_CHILDREN).getJSONObject(i).getString(ProtocolConstants.KEY_NAME);
if (!remoteBranchName.equals("origin/a")) {
i = 1;
remoteBranchName = remoteBranchLocations1.getJSONObject(0).getJSONArray(ProtocolConstants.KEY_CHILDREN).getJSONObject(i).getString(ProtocolConstants.KEY_NAME);
}
assertEquals("origin/a", remoteBranchName);
String remoteBranchLocation1 = remoteBranchLocations1.getJSONObject(0).getJSONArray(ProtocolConstants.KEY_CHILDREN).getJSONObject(i).getString(ProtocolConstants.KEY_LOCATION);
ServerStatus pushStatus = push(remoteBranchLocation1, Constants.HEAD, false);
assertEquals(true, pushStatus.isOK());
// clone 1 - list remote branches - expect 2
JSONObject remote1 = getRemote(gitRemoteUri1, 1, 0, Constants.DEFAULT_REMOTE_NAME);
String remoteLocation1 = remote1.getString(ProtocolConstants.KEY_LOCATION);
request = GitRemoteTest.getGetGitRemoteRequest(remoteLocation1);
response = webConversation.getResponse(request);
ServerStatus status = waitForTask(response);
assertTrue(status.toString(), status.isOK());
remote1 = status.getJsonData();
JSONArray refsArray = remote1.getJSONArray(ProtocolConstants.KEY_CHILDREN);
assertEquals(2, refsArray.length());
JSONObject ref = refsArray.getJSONObject(0);
assertEquals(Constants.R_REMOTES + Constants.DEFAULT_REMOTE_NAME + "/" + newBranchName, ref.getString(ProtocolConstants.KEY_FULL_NAME));
ref = refsArray.getJSONObject(1);
assertEquals(Constants.R_REMOTES + Constants.DEFAULT_REMOTE_NAME + "/" + Constants.MASTER, ref.getString(ProtocolConstants.KEY_FULL_NAME));
// clone 2
JSONObject clone2 = clone(clonePath[1]);
String cloneLocation2 = clone2.getString(ProtocolConstants.KEY_LOCATION);
String contentLocation2 = clone2.getString(ProtocolConstants.KEY_CONTENT_LOCATION);
// clone 2 - get project2 metadata
request = getGetRequest(contentLocation2);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject project2 = new JSONObject(response.getText());
JSONObject gitSection2 = project2.getJSONObject(GitConstants.KEY_GIT);
String gitRemoteUri2 = gitSection2.getString(GitConstants.KEY_REMOTE);
// clone 2 - check if the branch "a" is available
JSONObject remote2 = getRemote(gitRemoteUri2, 1, 0, Constants.DEFAULT_REMOTE_NAME);
String remoteLocation2 = remote2.getString(ProtocolConstants.KEY_LOCATION);
request = GitRemoteTest.getGetGitRemoteRequest(remoteLocation2);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
remote2 = new JSONObject(response.getText());
refsArray = remote2.getJSONArray(ProtocolConstants.KEY_CHILDREN);
assertEquals(2, refsArray.length());
ref = refsArray.getJSONObject(0);
assertEquals(Constants.R_REMOTES + Constants.DEFAULT_REMOTE_NAME + "/" + Constants.MASTER, ref.getString(ProtocolConstants.KEY_FULL_NAME));
ref = refsArray.getJSONObject(1);
assertEquals(Constants.R_REMOTES + Constants.DEFAULT_REMOTE_NAME + "/" + newBranchName, ref.getString(ProtocolConstants.KEY_FULL_NAME));
String remoteBranchLocation2 = ref.getString(ProtocolConstants.KEY_LOCATION);
// clone 2 - checkout branch "a"
response = checkoutBranch(cloneLocation2, newBranchName);
// clone 1 - delete remote branch "a"
push(remoteBranchLocation1, "", false, false);
// clone 1 - list remote branches - expect 1
request = GitRemoteTest.getGetGitRemoteRequest(remoteLocation1);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
remote1 = new JSONObject(response.getText());
refsArray = remote1.getJSONArray(ProtocolConstants.KEY_CHILDREN);
assertEquals(1, refsArray.length());
ref = refsArray.getJSONObject(0);
assertEquals(Constants.R_REMOTES + Constants.DEFAULT_REMOTE_NAME + "/" + Constants.MASTER, ref.getString(ProtocolConstants.KEY_FULL_NAME));
// clone 2 - fetch
request = GitFetchTest.getPostGitRemoteRequest(remoteBranchLocation2, true, false);
response = webConversation.getResponse(request);
status = waitForTask(response);
assertFalse(status.toString(), status.isOK());
// clone 2 - fetch task should fail
JSONObject statusJson = status.toJSON();
JSONObject result = statusJson.has("Result") ? statusJson.getJSONObject("Result") : statusJson;
assertEquals("Error", result.getString("Severity"));
}
}
@Test
public void testPushFromLog() throws Exception {
// clone a repo
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
String workspaceId = workspaceIdFromLocation(workspaceLocation);
JSONObject project = createProjectOrLink(workspaceLocation, getMethodName().concat("Project"), null);
IPath clonePath = getClonePath(workspaceId, project);
clone(clonePath);
// 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());
JSONObject gitSection = project.getJSONObject(GitConstants.KEY_GIT);
String gitIndexUri = gitSection.getString(GitConstants.KEY_INDEX);
String gitHeadUri = gitSection.getString(GitConstants.KEY_HEAD);
// log
JSONArray commitsArray = log(gitHeadUri);
assertEquals(1, commitsArray.length());
// change
JSONObject testTxt = getChild(project, "test.txt");
modifyFile(testTxt, "incoming change");
// add
request = GitAddTest.getPutGitIndexRequest(gitIndexUri);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// commit
request = GitCommitTest.getPostGitCommitRequest(gitHeadUri, "incoming change commit", false);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// log again
JSONObject logResponse = logObject(gitHeadUri);
assertEquals(2, logResponse.getJSONArray(ProtocolConstants.KEY_CHILDREN).length());
JSONObject toRefBranch = logResponse.getJSONObject(GitConstants.KEY_LOG_TO_REF);
JSONArray remoteLocations = toRefBranch.getJSONArray(GitConstants.KEY_REMOTE);
assertEquals(1, remoteLocations.length());
String remoteBranchLocation = remoteLocations.getJSONObject(0).getJSONArray(ProtocolConstants.KEY_CHILDREN).getJSONObject(0).getString(ProtocolConstants.KEY_LOCATION);
// push
request = getPostGitRemoteRequest(remoteBranchLocation, Constants.HEAD, false, false);
response = webConversation.getResponse(request);
ServerStatus status = waitForTask(response);
assertTrue(status.toString(), status.isOK());
}
@Test
public void testPushRejected() throws Exception {
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
String workspaceId = workspaceIdFromLocation(workspaceLocation);
// clone1
JSONObject project1 = createProjectOrLink(workspaceLocation, getMethodName().concat("Project1"), null);
IPath clonePath1 = getClonePath(workspaceId, project1);
clone(clonePath1);
// get project1 metadata
WebRequest request = getGetRequest(project1.getString(ProtocolConstants.KEY_CONTENT_LOCATION));
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
project1 = new JSONObject(response.getText());
JSONObject gitSection1 = project1.optJSONObject(GitConstants.KEY_GIT);
assertNotNull(gitSection1);
String gitRemoteUri1 = gitSection1.optString(GitConstants.KEY_REMOTE);
String gitIndexUri1 = gitSection1.optString(GitConstants.KEY_INDEX);
String gitHeadUri1 = gitSection1.optString(GitConstants.KEY_HEAD);
// clone2
JSONObject project2 = createProjectOrLink(workspaceLocation, getMethodName().concat("Project2"), null);
IPath clonePath2 = getClonePath(workspaceId, project2);
clone(clonePath2);
// get project2 metadata
request = getGetRequest(project2.getString(ProtocolConstants.KEY_CONTENT_LOCATION));
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
project2 = new JSONObject(response.getText());
JSONObject gitSection2 = project2.optJSONObject(GitConstants.KEY_GIT);
assertNotNull(gitSection2);
String gitRemoteUri2 = gitSection2.getString(GitConstants.KEY_REMOTE);
String gitIndexUri2 = gitSection2.getString(GitConstants.KEY_INDEX);
String gitHeadUri2 = gitSection2.getString(GitConstants.KEY_HEAD);
// clone1: change
JSONObject testTxt1 = getChild(project1, "test.txt");
modifyFile(testTxt1, "clone1 change");
// clone1: add
request = GitAddTest.getPutGitIndexRequest(gitIndexUri1);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// clone1: commit
request = GitCommitTest.getPostGitCommitRequest(gitHeadUri1, "clone1 change commit", false);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// clone1: push
ServerStatus pushStatus = push(gitRemoteUri1, 1, 0, Constants.MASTER, Constants.HEAD, false);
assertEquals(true, pushStatus.isOK());
// clone2: change
JSONObject testTxt2 = getChild(project2, "test.txt");
modifyFile(testTxt2, "clone2 change");
// clone2: add
request = GitAddTest.getPutGitIndexRequest(gitIndexUri2);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// clone2: commit
request = GitCommitTest.getPostGitCommitRequest(gitHeadUri2, "clone2 change commit", false);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// clone2: push
pushStatus = push(gitRemoteUri2, 1, 0, Constants.MASTER, Constants.HEAD, false);
JSONObject jo = pushStatus.getJsonData();
assertEquals("Error", jo.get("Severity"));
JSONArray up = (JSONArray) jo.get("Updates");
assertEquals(1, up.length());
Status pushResult = Status.valueOf((String) ((JSONObject) up.get(0)).get("Result"));
assertEquals(Status.REJECTED_NONFASTFORWARD, pushResult);
}
@Test
public void testPushRemoteRejected() throws Exception {
// clone a repo
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
String workspaceId = workspaceIdFromLocation(workspaceLocation);
JSONObject project = createProjectOrLink(workspaceLocation, getMethodName().concat("Project"), null);
IPath clonePath = getClonePath(workspaceId, project);
clone(clonePath);
// 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());
JSONObject gitSection = project.getJSONObject(GitConstants.KEY_GIT);
String gitRemoteUri = gitSection.getString(GitConstants.KEY_REMOTE);
// 1st commit
JSONObject testTxt = getChild(project, "test.txt");
modifyFile(testTxt, "1st change");
addFile(testTxt);
commitFile(testTxt, "1st change commit", false);
// push
ServerStatus pushStatus = push(gitRemoteUri, 1, 0, Constants.MASTER, Constants.HEAD, false);
assertEquals(IStatus.OK, pushStatus.getSeverity());
// 2nd commit
modifyFile(testTxt, "2nd change");
addFile(testTxt);
commitFile(testTxt, "2nd change commit", false);
FileUtils.delete(new File(gitDir, Constants.DOT_GIT + "/objects/pack/"), FileUtils.RECURSIVE);
pushStatus = push(gitRemoteUri, 1, 0, Constants.MASTER, Constants.HEAD, false);
JSONObject jo = pushStatus.getJsonData();
JSONArray up = (JSONArray) jo.get("Updates");
assertEquals(1, up.length());
assertEquals("Error", jo.get("Severity"));
Status pushResult = Status.valueOf((String) ((JSONObject) up.get(0)).get("Result"));
assertEquals(Status.REJECTED_OTHER_REASON, pushResult);
assertTrue(((JSONObject) up.get(0)).getString("Message"), ((JSONObject) up.get(0)).getString("Message").matches("^object [\\da-f]+ missing$"));
}
@Test
public void testForcedPush() throws Exception {
// overwrite system settings, allow forced pushes, see bug 371881
StoredConfig cfg = db.getConfig();
cfg.setBoolean("receive", null, "denyNonFastforwards", false);
cfg.save();
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
IPath[][] clonePaths = createTestClonePairs(workspaceLocation);
for (IPath[] clonePath : clonePaths) {
// clone1
String contentLocation1 = clone(clonePath[0]).getString(ProtocolConstants.KEY_CONTENT_LOCATION);
// get project1 metadata
WebRequest request = getGetRequest(contentLocation1);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject project1 = new JSONObject(response.getText());
JSONObject gitSection1 = project1.getJSONObject(GitConstants.KEY_GIT);
String gitRemoteUri1 = gitSection1.getString(GitConstants.KEY_REMOTE);
String gitIndexUri1 = gitSection1.getString(GitConstants.KEY_INDEX);
String gitHeadUri1 = gitSection1.getString(GitConstants.KEY_HEAD);
// clone2
String contentLocation2 = clone(clonePath[1]).getString(ProtocolConstants.KEY_CONTENT_LOCATION);
// get project2 metadata
request = getGetRequest(contentLocation2);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject project2 = new JSONObject(response.getText());
JSONObject gitSection2 = project2.getJSONObject(GitConstants.KEY_GIT);
String gitRemoteUri2 = gitSection2.getString(GitConstants.KEY_REMOTE);
String gitIndexUri2 = gitSection2.getString(GitConstants.KEY_INDEX);
String gitHeadUri2 = gitSection2.getString(GitConstants.KEY_HEAD);
// clone1: change
JSONObject testTxt1 = getChild(project1, "test.txt");
modifyFile(testTxt1, "clone1 change");
// clone1: add
request = GitAddTest.getPutGitIndexRequest(gitIndexUri1);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// clone1: commit
request = GitCommitTest.getPostGitCommitRequest(gitHeadUri1, "clone1 change commit", false);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// clone1: push
ServerStatus pushStatus = push(gitRemoteUri1, 1, 0, Constants.MASTER, Constants.HEAD, false);
assertEquals(true, pushStatus.isOK());
// clone2: change
JSONObject testTxt2 = getChild(project2, "test.txt");
modifyFile(testTxt2, "clone2 change");
// clone2: add
request = GitAddTest.getPutGitIndexRequest(gitIndexUri2);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// clone2: commit
request = GitCommitTest.getPostGitCommitRequest(gitHeadUri2, "clone2 change commit", false);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// clone2: push
pushStatus = push(gitRemoteUri2, 1, 0, Constants.MASTER, Constants.HEAD, false);
JSONObject jo = pushStatus.getJsonData();
JSONArray up = (JSONArray) jo.get("Updates");
assertEquals(1, up.length());
assertEquals("Error", jo.get("Severity"));
Status pushResult = Status.valueOf((String) ((JSONObject) up.get(0)).get("Result"));
assertEquals(Status.REJECTED_NONFASTFORWARD, pushResult);
// clone2: forced push
pushStatus = push(gitRemoteUri2, 1, 0, Constants.MASTER, Constants.HEAD, false, true);
jo = pushStatus.getJsonData();
up = (JSONArray) jo.get("Updates");
assertEquals(1, up.length());
assertEquals("OK", ((JSONObject) up.get(0)).get("Result"));
}
}
@Test
public void testPushTags() throws Exception {
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
String workspaceId = workspaceIdFromLocation(workspaceLocation);
// clone1
JSONObject project1 = createProjectOrLink(workspaceLocation, getMethodName().concat("Project1"), null);
IPath clonePath1 = getClonePath(workspaceId, project1);
clone(clonePath1);
// get project1 metadata
WebRequest request = getGetRequest(project1.getString(ProtocolConstants.KEY_CONTENT_LOCATION));
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
project1 = new JSONObject(response.getText());
JSONObject gitSection1 = project1.optJSONObject(GitConstants.KEY_GIT);
assertNotNull(gitSection1);
String gitRemoteUri1 = gitSection1.optString(GitConstants.KEY_REMOTE);
String gitTagUri1 = gitSection1.optString(GitConstants.KEY_TAG);
// clone2
JSONObject project2 = createProjectOrLink(workspaceLocation, getMethodName().concat("Project2"), null);
IPath clonePath2 = getClonePath(workspaceId, project2);
clone(clonePath2);
// get project2 metadata
request = getGetRequest(project2.getString(ProtocolConstants.KEY_CONTENT_LOCATION));
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
project2 = new JSONObject(response.getText());
JSONObject gitSection2 = project2.getJSONObject(GitConstants.KEY_GIT);
String gitRemoteUri2 = gitSection2.getString(GitConstants.KEY_REMOTE);
String gitHeadUri2 = gitSection2.getString(GitConstants.KEY_HEAD);
String gitTagUri2 = gitSection2.getString(GitConstants.KEY_TAG);
// clone1: tag HEAD with 'tag'
tag(gitTagUri1, "tag", Constants.HEAD);
ServerStatus pushStatus = push(gitRemoteUri1, 1, 0, Constants.MASTER, Constants.HEAD, true);
assertEquals(true, pushStatus.isOK());
// clone2: list tags
JSONArray tags = listTags(gitTagUri2);
assertEquals(0, tags.length());
// clone2: fetch + merge
JSONObject remoteBranch = getRemoteBranch(gitRemoteUri2, 1, 0, Constants.MASTER);
String remoteBranchLocation2 = remoteBranch.getString(ProtocolConstants.KEY_LOCATION);
fetch(remoteBranchLocation2);
String id = remoteBranch.getString(ProtocolConstants.KEY_ID);
merge(gitHeadUri2, id);
// clone2: list tags again
tags = listTags(gitTagUri2);
assertEquals(1, tags.length());
}
@Test
public void testPushNewBranchToSecondaryRemote() throws Exception {
// see bug 353557
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
IPath[] clonePaths = createTestProjects(workspaceLocation);
String workspaceId = workspaceIdFromLocation(workspaceLocation);
for (int i = 0; i < clonePaths.length; i++) {
IPath clonePath = clonePaths[i];
// clone a repo
JSONObject clone = clone(clonePath);
String cloneContentLocation = clone.getString(ProtocolConstants.KEY_CONTENT_LOCATION);
String cloneLocation = clone.getString(ProtocolConstants.KEY_LOCATION);
String branchesLocation = clone.getString(GitConstants.KEY_BRANCH);
// get project/folder metadata
WebRequest request = getGetRequest(cloneContentLocation);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject folder = new JSONObject(response.getText());
String remotesLocation = clone.getString(GitConstants.KEY_REMOTE);
// expect only origin
getRemote(remotesLocation, 1, 0, Constants.DEFAULT_REMOTE_NAME);
// create secondary repository
IPath randomLocation = createTempDir();
randomLocation = randomLocation.addTrailingSeparator().append(Constants.DOT_GIT);
File dotGitDir = randomLocation.toFile().getCanonicalFile();
Repository db2 = FileRepositoryBuilder.create(dotGitDir);
assertFalse(dotGitDir.exists());
db2.create(false /* non bare */);
toClose.add(db2);
// dummy commit to start off master branch
File dummyFile = new File(dotGitDir.getParentFile(), "test.txt");
dummyFile.createNewFile();
createFile(dummyFile.toURI(), "dummy");
Git git2 = new Git(db2);
git2.add().addFilepattern(".").call();
git2.commit().setMessage("dummy commit").call();
// create remote
response = addRemote(remotesLocation, "secondary", dotGitDir.getParentFile().toURI().toURL().toString());
String secondaryRemoteLocation = response.getHeaderField(ProtocolConstants.HEADER_LOCATION);
assertNotNull(secondaryRemoteLocation);
// list remotes
request = getGetRequest(remotesLocation);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject remotes = new JSONObject(response.getText());
JSONArray remotesArray = remotes.getJSONArray(ProtocolConstants.KEY_CHILDREN);
// expect origin and new remote
assertEquals(2, remotesArray.length());
// create branch, checkout
response = branch(branchesLocation, "branch");
JSONObject branch = new JSONObject(response.getText());
checkoutBranch(cloneLocation, "branch");
// modify, add, commit
JSONObject testTxt = getChild(folder, "test.txt");
modifyFile(testTxt, "branch change");
addFile(testTxt);
commitFile(testTxt, "branch commit", false);
// push the new branch
JSONArray remoteBranchLocations = branch.getJSONArray(GitConstants.KEY_REMOTE);
assertEquals(2, remoteBranchLocations.length());
String remoteBranchLocation = null;
if (remoteBranchLocations.getJSONObject(0).getString(ProtocolConstants.KEY_NAME).equals("secondary")) {
remoteBranchLocation = remoteBranchLocations.getJSONObject(0).getJSONArray(ProtocolConstants.KEY_CHILDREN).getJSONObject(0).getString(ProtocolConstants.KEY_LOCATION);
} else if (remoteBranchLocations.getJSONObject(1).getString(ProtocolConstants.KEY_NAME).equals("secondary")) {
remoteBranchLocation = remoteBranchLocations.getJSONObject(1).getJSONArray(ProtocolConstants.KEY_CHILDREN).getJSONObject(0).getString(ProtocolConstants.KEY_LOCATION);
}
assertNotNull(remoteBranchLocation);
ServerStatus pushStatus = push(remoteBranchLocation, Constants.HEAD, false);
assertTrue(pushStatus.isOK());
// see bug 354144
request = getGetRequest(branch.getString(ProtocolConstants.KEY_LOCATION));
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
branch = new JSONObject(response.getText());
remoteBranchLocations = branch.getJSONArray(GitConstants.KEY_REMOTE);
// now, there should be only one remote branch returned
assertEquals(1, remoteBranchLocations.length());
assertEquals("secondary", remoteBranchLocations.getJSONObject(0).getString(ProtocolConstants.KEY_NAME));
assertEquals("secondary/branch", remoteBranchLocations.getJSONObject(0).getJSONArray(ProtocolConstants.KEY_CHILDREN).getJSONObject(0).getString(ProtocolConstants.KEY_NAME));
// clone the secondary branch and check if the new branch is there
JSONObject secondProject = createProjectOrLink(workspaceLocation, getMethodName().concat("-second-").concat(Integer.toString(i)), null);
IPath secondClonePath = getClonePath(workspaceId, secondProject);
URIish uri = new URIish(dotGitDir.getParentFile().toURI().toURL());
JSONObject clone2 = clone(uri, null, secondClonePath, null, null, null);
String cloneLocation2 = clone2.getString(ProtocolConstants.KEY_LOCATION);
String branchesLocation2 = clone2.getString(GitConstants.KEY_BRANCH);
String remotesLocation2 = clone2.getString(GitConstants.KEY_REMOTE);
// expecting two branches, second named "branch"
JSONObject remoteBranch2 = getRemoteBranch(remotesLocation2, 2, 1, "branch");
String remoteBranchName2 = remoteBranch2.getString(ProtocolConstants.KEY_NAME);
// create tracking branch and check it out
response = branch(branchesLocation2, null /* deduct from the remote branch name */, remoteBranchName2);
JSONObject branch2 = new JSONObject(response.getText());
response = checkoutBranch(cloneLocation2, branch2.getString(ProtocolConstants.KEY_NAME));
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
// check file content
String cloneContentLocation2 = clone2.getString(ProtocolConstants.KEY_CONTENT_LOCATION);
request = getGetRequest(cloneContentLocation2);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject folder2 = new JSONObject(response.getText());
JSONObject testTxt2 = getChild(folder2, "test.txt");
assertEquals("branch change", getFileContent(testTxt2));
}
}
static WebRequest getPostGitRemoteRequest(String location, String srcRef, boolean tags, boolean force) throws JSONException, UnsupportedEncodingException {
String requestURI = toAbsoluteURI(location);
JSONObject body = new JSONObject();
if (srcRef != null)
body.put(GitConstants.KEY_PUSH_SRC_REF, srcRef);
body.put(GitConstants.KEY_PUSH_TAGS, tags);
body.put(GitConstants.KEY_FORCE, force);
WebRequest request = new PostMethodWebRequest(requestURI, IOUtilities.toInputStream(body.toString()), "UTF-8");
request.setHeaderField(ProtocolConstants.HEADER_ORION_VERSION, "1");
setAuthentication(request);
return request;
}
static WebRequest getPostGitRemoteRequest(String location, String srcRef, boolean tags, boolean force, String name, String kh, byte[] privk, byte[] pubk, byte[] p) throws JSONException, UnsupportedEncodingException {
String requestURI = toAbsoluteURI(location);
JSONObject body = new JSONObject();
body.put(ProtocolConstants.KEY_NAME, name);
if (kh != null)
body.put(GitConstants.KEY_KNOWN_HOSTS, kh);
if (privk != null)
body.put(GitConstants.KEY_PRIVATE_KEY, new String(privk));
if (pubk != null)
body.put(GitConstants.KEY_PUBLIC_KEY, new String(pubk));
if (p != null)
body.put(GitConstants.KEY_PASSPHRASE, new String(p));
if (srcRef != null)
body.put(GitConstants.KEY_PUSH_SRC_REF, srcRef);
body.put(GitConstants.KEY_PUSH_TAGS, tags);
body.put(GitConstants.KEY_FORCE, force);
WebRequest request = new PostMethodWebRequest(requestURI, IOUtilities.toInputStream(body.toString()), "UTF-8");
request.setHeaderField(ProtocolConstants.HEADER_ORION_VERSION, "1");
setAuthentication(request);
return request;
}
}