/*******************************************************************************
* 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 static org.junit.Assert.fail;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.RebaseCommand.Operation;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryCache;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.transport.URIish;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.FileUtils;
import org.eclipse.orion.internal.server.core.metastore.SimpleMetaStore;
import org.eclipse.orion.internal.server.core.metastore.SimpleMetaStoreUtil;
import org.eclipse.orion.internal.server.servlets.workspace.ServletTestingSupport;
import org.eclipse.orion.server.core.IOUtilities;
import org.eclipse.orion.server.core.LogHelper;
import org.eclipse.orion.server.core.OrionConfiguration;
import org.eclipse.orion.server.core.ProtocolConstants;
import org.eclipse.orion.server.core.ServerStatus;
import org.eclipse.orion.server.core.metastore.IMetaStore;
import org.eclipse.orion.server.core.metastore.ProjectInfo;
import org.eclipse.orion.server.core.metastore.WorkspaceInfo;
import org.eclipse.orion.server.core.tasks.TaskInfo;
import org.eclipse.orion.server.git.GitConstants;
import org.eclipse.orion.server.git.objects.Blame;
import org.eclipse.orion.server.git.objects.Branch;
import org.eclipse.orion.server.git.objects.Clone;
import org.eclipse.orion.server.git.objects.Commit;
import org.eclipse.orion.server.git.objects.ConfigOption;
import org.eclipse.orion.server.git.objects.Remote;
import org.eclipse.orion.server.git.objects.RemoteBranch;
import org.eclipse.orion.server.git.objects.Status;
import org.eclipse.orion.server.git.objects.Tag;
import org.eclipse.orion.server.git.servlets.GitServlet;
import org.eclipse.orion.server.git.servlets.GitUtils;
import org.eclipse.orion.server.tests.AbstractServerTest;
import org.eclipse.orion.server.tests.servlets.files.FileSystemTest;
import org.eclipse.orion.server.tests.servlets.internal.DeleteMethodWebRequest;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.xml.sax.SAXException;
import com.meterware.httpunit.GetMethodWebRequest;
import com.meterware.httpunit.PostMethodWebRequest;
import com.meterware.httpunit.PutMethodWebRequest;
import com.meterware.httpunit.WebConversation;
import com.meterware.httpunit.WebRequest;
import com.meterware.httpunit.WebResponse;
public abstract class GitTest extends FileSystemTest {
static final String GIT_SERVLET_LOCATION = "gitapi/";
File gitDir;
File testFile;
protected Repository db;
protected static final List<Repository> toClose = new ArrayList<Repository>();
@BeforeClass
public static void setupWorkspace() {
initializeWorkspaceLocation();
}
protected static String sshRepo;
protected static String sshRepo2;
protected static char[] password;
protected static String knownHosts;
protected static String knownHosts2;
protected static byte[] privateKey;
protected static byte[] publicKey;
protected static byte[] passphrase;
protected static void readSshProperties() {
String propertiesFile = System.getProperty("orion.tests.ssh");
if (propertiesFile == null)
return;
Map<String, String> properties = new HashMap<String, String>();
try {
File file = new File(propertiesFile);
if (file.isDirectory())
file = new File(file, "sshtest.properties");
BufferedReader reader = new BufferedReader(new FileReader(file));
try {
for (String line; (line = reader.readLine()) != null;) {
if (line.startsWith("#"))
continue;
int sep = line.indexOf("=");
String property = line.substring(0, sep).trim();
String value = line.substring(sep + 1).trim();
properties.put(property, value);
}
} finally {
reader.close();
}
// initialize constants
sshRepo = properties.get("host");
sshRepo2 = properties.get("host2");
password = properties.get("password").toCharArray();
knownHosts = properties.get("knownHosts");
knownHosts2 = properties.get("knownHosts2");
privateKey = loadFileContents(properties.get("privateKeyPath")).getBytes();
publicKey = loadFileContents(properties.get("publicKeyPath")).getBytes();
passphrase = properties.get("passphrase").getBytes();
} catch (Exception e) {
e.printStackTrace();
System.err.println("Could not read ssh properties file: " + propertiesFile);
}
}
@Before
public void setUp() throws CoreException, IOException, GitAPIException {
webConversation = new WebConversation();
webConversation.setExceptionsThrownOnErrorStatus(false);
setUpAuthorization();
createRepository();
ServletTestingSupport.allowedPrefixes = gitDir.toString();
GitUtils._testAllowFileScheme(true);
}
@After
public void tearDown() throws Exception {
//close all repositories
for (Repository repo : toClose) {
repo.close();
}
toClose.clear();
FileUtils.delete(gitDir, FileUtils.RECURSIVE);
}
/**
* Creates a request to get the status result for the given location.
* @param location Either an absolute URI, or a workspace-relative URI
*/
protected WebRequest getGetGitStatusRequest(String location) {
String requestURI = toAbsoluteURI(location);
WebRequest request = new GetMethodWebRequest(requestURI);
request.setHeaderField(ProtocolConstants.HEADER_ORION_VERSION, "1");
setAuthentication(request);
return request;
}
protected JSONObject linkProject(String contentLocation, String projectName) throws JSONException, IOException, SAXException {
// TODO: remove me
createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
return createProjectOrLink(workspaceLocation, projectName, contentLocation);
}
protected JSONObject createProjectOrLink(URI workspaceLocationURI, String projectName, String contentLocation) throws JSONException, IOException, SAXException {
JSONObject body = new JSONObject();
if (contentLocation != null) {
body.put(ProtocolConstants.KEY_CONTENT_LOCATION, contentLocation);
ServletTestingSupport.allowedPrefixes = contentLocation;
}
WebRequest request = new PostMethodWebRequest(workspaceLocationURI.toString(), IOUtilities.toInputStream(body.toString()), "UTF-8");
if (projectName != null)
request.setHeaderField(ProtocolConstants.HEADER_SLUG, projectName);
request.setHeaderField(ProtocolConstants.HEADER_ORION_VERSION, "1");
setAuthentication(request);
WebResponse response = webConversation.getResponse(request);
if (response.getResponseCode() != HttpURLConnection.HTTP_CREATED) {
String msg = response.getText();
LogHelper.log(new org.eclipse.core.runtime.Status(IStatus.ERROR, "org.eclipse.orion.server.tests", msg));
assertTrue("Unexpected failure cloning: " + msg, false);
}
JSONObject project = new JSONObject(response.getText());
assertEquals(projectName, project.getString(ProtocolConstants.KEY_NAME));
String projectId = project.optString(ProtocolConstants.KEY_ID, null);
assertNotNull(projectId);
IPath workspacePath = new Path(workspaceLocationURI.getPath());
String workspaceId = workspacePath.segment(workspacePath.segmentCount() - 1);
testProjectBaseLocation = "/" + workspaceId + '/' + projectName;
testProjectLocalFileLocation = "/" + project.optString(ProtocolConstants.KEY_ID, null);
return project;
}
protected void createRepository() throws IOException, GitAPIException, CoreException {
IPath randomLocation = createTempDir();
gitDir = randomLocation.toFile();
randomLocation = randomLocation.addTrailingSeparator().append(Constants.DOT_GIT);
File dotGitDir = randomLocation.toFile().getCanonicalFile();
db = FileRepositoryBuilder.create(dotGitDir);
toClose.add(db);
assertFalse(dotGitDir.exists());
db.create(false /* non bare */);
testFile = new File(gitDir, "test.txt");
testFile.createNewFile();
createFile(testFile.toURI(), "test");
File folder = new File(gitDir, "folder");
folder.mkdir();
File folderFile = new File(folder, "folder.txt");
folderFile.createNewFile();
createFile(folderFile.toURI(), "folder");
Git git = new Git(db);
git.add().addFilepattern(".").call();
git.commit().setMessage("Initial commit").call();
// The system settings on eclipse.org was changed to receive.denyNonFastForward=true, see bug 343150.
// Imitate the same setup when running tests locally, see bug 371881.
StoredConfig cfg = db.getConfig();
cfg.setBoolean("receive", null, "denyNonFastforwards", true);
cfg.save();
}
private JSONObject waitForTaskCompletionObject(String taskLocation, String userName, String userPassword) throws IOException, SAXException, JSONException {
JSONObject status = null;
long start = System.currentTimeMillis();
while (true) {
WebRequest request = new GetMethodWebRequest(toAbsoluteURI(taskLocation));
setAuthentication(request, userName, userPassword);
WebResponse response = webConversation.getResponse(request);
String text = response.getText();
status = new JSONObject(text);
if (status.isNull(TaskInfo.KEY_TYPE))
fail("Unexpected task format: " + text);
String type = status.getString(TaskInfo.KEY_TYPE);
boolean running = "loadstart".equals(type) || "progress".equals(type);
if (!running)
break;
//timeout after reasonable time to avoid hanging tests
if (System.currentTimeMillis() - start > 15000)
assertTrue("The operation took too long", false);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
//ignore
}
}
assertNotNull(status);
return status;
}
protected ServerStatus waitForTask(WebResponse response) throws JSONException, IOException, SAXException {
return waitForTask(response, testUserLogin, testUserPassword);
}
protected ServerStatus waitForTask(WebResponse response, String userName, String userPassword) throws JSONException, IOException, SAXException {
if (response.getResponseCode() == HttpURLConnection.HTTP_ACCEPTED) {
String text = response.getText();
JSONObject taskDescription = new JSONObject(text);
String location = taskDescription.getString(ProtocolConstants.KEY_LOCATION);
JSONObject taskResponse = waitForTaskCompletionObject(location, userName, userPassword);
ServerStatus status = ServerStatus.fromJSON(taskResponse.getString("Result"));
return status;
}
try {
return ServerStatus.fromJSON(response.getText());
} catch (Exception e) {
JSONObject jsonData = null;
try {
jsonData = new JSONObject(response.getText());
} catch (Exception e1) {
//ignore
}
return new ServerStatus(response.getResponseCode() == HttpURLConnection.HTTP_OK ? IStatus.OK : IStatus.ERROR, response.getResponseCode(), response.getText(), jsonData, null);
}
}
protected String getMethodName() {
return testName.getMethodName();
}
protected static JSONObject getChildByKey(List<JSONObject> children, String key, String value) throws JSONException {
for (JSONObject child : children) {
if (value.equals(child.getString(key)))
return child;
}
return null;
}
protected static JSONObject getChildByName(List<JSONObject> children, String name) throws JSONException {
return getChildByKey(children, ProtocolConstants.KEY_NAME, name);
}
protected static Repository getRepositoryForContentLocation(String fileLocation) throws CoreException, IOException {
assertFileUri(fileLocation);
URI uri = URI.create(fileLocation);
IPath path = new Path(uri.getPath());
while (path.segmentCount() != 0 && !path.segment(0).equals("file")) {
path = path.removeFirstSegments(1);
}
//path format is /file/{workspaceId}/{projectName}[/path]
final IMetaStore metaStore = OrionConfiguration.getMetaStore();
WorkspaceInfo workspace = metaStore.readWorkspace(path.segment(1));
assertNotNull(workspace);
ProjectInfo wp = metaStore.readProject(workspace.getUniqueId(), path.segment(2));
assertNotNull(wp);
String userId = workspace.getUserId();
assertNotNull(userId);
IFileStore fsStore = getProjectStore(wp, userId);
fsStore = fsStore.getFileStore(path.removeFirstSegments(3));
File file = new File(fsStore.toURI());
if (RepositoryCache.FileKey.isGitRepository(file, FS.DETECTED)) {
// 'file' is already what we're looking for
} else if (RepositoryCache.FileKey.isGitRepository(new File(file, Constants.DOT_GIT), FS.DETECTED)) {
file = new File(file, Constants.DOT_GIT);
} else {
fail(fileLocation + " is not a repository");
}
Repository result = FileRepositoryBuilder.create(file);
toClose.add(result);
return result;
}
// see org.eclipse.orion.internal.server.servlets.workspace.WorkspaceResourceHandler.generateProjectLocation(WebProject, String)
private static IFileStore getProjectStore(ProjectInfo project, String user) throws CoreException {
IFileStore projectStore = OrionConfiguration.getMetaStore().getDefaultContentLocation(project);
if (!projectStore.fetchInfo().exists()) {
projectStore.mkdir(EFS.NONE, null);
}
return projectStore;
}
// clone
public String getCloneUri(String statusUri) throws JSONException, IOException, SAXException, CoreException {
assertStatusUri(statusUri);
WebRequest request = getGetGitStatusRequest(statusUri);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject status = new JSONObject(response.getText());
String cloneUri = status.getString(GitConstants.KEY_CLONE);
assertCloneUri(cloneUri);
return cloneUri;
}
protected JSONObject clone(URIish uri, IPath workspacePath, IPath filePath, String name, String kh, char[] p) throws JSONException, IOException, SAXException, CoreException {
// clone
WebRequest request = getPostGitCloneRequest(uri, workspacePath, filePath, name, kh, p);
ServerStatus status = waitForTask(webConversation.getResponse(request));
assertTrue(status.toString(), status.isOK());
String cloneLocation = status.getJsonData().getString(ProtocolConstants.KEY_LOCATION);
assertNotNull(cloneLocation);
// validate the clone metadata
WebResponse response = webConversation.getResponse(getGetRequest(cloneLocation));
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject clones = new JSONObject(response.getText());
assertTrue("Clone doesn't have children at " + cloneLocation, clones.has(ProtocolConstants.KEY_CHILDREN));
JSONArray clonesArray = clones.getJSONArray(ProtocolConstants.KEY_CHILDREN);
assertEquals(1, clonesArray.length());
JSONObject clone = clonesArray.getJSONObject(0);
String n = clone.getString(ProtocolConstants.KEY_NAME);
if (filePath != null)
assertTrue(n.equals(filePath.lastSegment()));
if (workspacePath != null)
if (name != null)
assertEquals(name, n);
else
assertEquals(uri.getHumanishName(), n);
assertCloneUri(clone.getString(ProtocolConstants.KEY_LOCATION));
assertFileUri(clone.getString(ProtocolConstants.KEY_CONTENT_LOCATION));
assertRemoteUri(clone.getString(GitConstants.KEY_REMOTE));
assertBranchUri(clone.getString(GitConstants.KEY_BRANCH));
return clone;
}
// init
protected JSONObject init(IPath workspacePath, IPath filePath, String name) throws JSONException, IOException, SAXException, CoreException {
// no Git URL for init
WebRequest request = getPostGitCloneRequest(null, workspacePath, filePath, name, null, null);
ServerStatus status = waitForTask(webConversation.getResponse(request));
assertTrue(status.toString(), status.isOK());
String cloneLocation = status.getJsonData().getString(ProtocolConstants.KEY_LOCATION);
assertNotNull(cloneLocation);
// validate the clone metadata
WebResponse response = webConversation.getResponse(getGetRequest(cloneLocation));
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject clones = new JSONObject(response.getText());
assertTrue("Clone doesn't have children at " + cloneLocation, clones.has(ProtocolConstants.KEY_CHILDREN));
JSONArray clonesArray = clones.getJSONArray(ProtocolConstants.KEY_CHILDREN);
assertEquals(1, clonesArray.length());
JSONObject clone = clonesArray.getJSONObject(0);
String n = clone.getString(ProtocolConstants.KEY_NAME);
if (filePath != null)
assertTrue(n.equals(filePath.lastSegment()));
if (workspacePath != null && name != null)
assertEquals(name, n);
assertCloneUri(clone.getString(ProtocolConstants.KEY_LOCATION));
assertFileUri(clone.getString(ProtocolConstants.KEY_CONTENT_LOCATION));
assertRemoteUri(clone.getString(GitConstants.KEY_REMOTE));
assertBranchUri(clone.getString(GitConstants.KEY_BRANCH));
return clone;
}
protected JSONObject clone(IPath workspacePath, IPath filePath, String name) throws JSONException, IOException, SAXException, CoreException {
URIish uri = new URIish(gitDir.toURI().toURL());
return clone(uri, workspacePath, filePath, name, null, null);
}
protected JSONObject clone(IPath clonePath) throws JSONException, IOException, SAXException, CoreException {
URIish uri = new URIish(gitDir.toURI().toURL());
return clone(uri, null, clonePath, null, null, null);
}
/**
* Returns the HTTP resource location for the given workspace and project.
* @param workspaceId
* @param project
*/
protected IPath getClonePath(String workspaceId, JSONObject project) {
String projectName = project.optString(ProtocolConstants.KEY_NAME, null);
assertNotNull(projectName);
IPath serverPath = new Path(AbstractServerTest.SERVER_URI.getPath());
return serverPath.append("file").append(workspaceId).append(projectName).makeAbsolute();
}
/**
* Creates a clone in the given workspace and project.
*/
protected JSONObject clone(String workspaceId, JSONObject project) throws JSONException, IOException, SAXException, CoreException {
return clone(getClonePath(workspaceId, project));
}
/**
* Returns <code>JSONObject</code> representing clone. Assume there is single clone for the given <code>gitResource</code>.
*
* @param gitResource a project, folder or file with {@link GitConstants.KEY_GIT} property
* @return
* @throws JSONException
* @throws IOException
* @throws SAXException
*/
protected JSONObject getCloneForGitResource(JSONObject gitResource) throws JSONException, IOException, SAXException {
String cloneLocation = gitResource.getJSONObject(GitConstants.KEY_GIT).getString(GitConstants.KEY_CLONE);
WebRequest request = getGetRequest(cloneLocation);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject clones = new JSONObject(response.getText());
JSONArray clonesArray = clones.getJSONArray(ProtocolConstants.KEY_CHILDREN);
assertEquals(1, clonesArray.length());
return clonesArray.getJSONObject(0);
}
// remotes
protected JSONObject getRemote(String gitRemoteUri, int size, int i, String name) throws IOException, SAXException, JSONException {
assertRemoteUri(gitRemoteUri);
WebRequest request = GitRemoteTest.getGetGitRemoteRequest(gitRemoteUri);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject remotes = new JSONObject(response.getText());
assertEquals(Remote.TYPE, remotes.getString(ProtocolConstants.KEY_TYPE));
JSONArray remotesArray = remotes.getJSONArray(ProtocolConstants.KEY_CHILDREN);
assertEquals(size, remotesArray.length());
JSONObject remote = remotesArray.getJSONObject(i);
assertNotNull(remote);
assertEquals(name, remote.getString(ProtocolConstants.KEY_NAME));
String remoteLocation = remote.getString(ProtocolConstants.KEY_LOCATION);
assertNotNull(remoteLocation);
return remote;
}
protected WebResponse addRemote(String remotesLocation, String name, String uri) throws JSONException, IOException, SAXException {
return addRemote(remotesLocation, name, uri, null, null, null);
}
protected WebResponse addRemote(String remotesLocation, String name, String uri, String fetchRefSpec, String pushUri, String pushRefSpec) throws JSONException, IOException, SAXException {
assertRemoteUri(remotesLocation);
WebRequest request = GitRemoteTest.getPostGitRemoteRequest(remotesLocation, name, uri, fetchRefSpec, pushUri, pushRefSpec);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_CREATED, response.getResponseCode());
return response;
}
protected JSONObject getRemoteBranch(String gitRemoteUri, int size, int i, String name) throws IOException, SAXException, JSONException {
assertRemoteUri(gitRemoteUri);
JSONObject remote = getRemote(gitRemoteUri, 1, 0, Constants.DEFAULT_REMOTE_NAME);
String remoteLocation = remote.getString(ProtocolConstants.KEY_LOCATION);
WebRequest request = GitRemoteTest.getGetGitRemoteRequest(remoteLocation);
WebResponse response = webConversation.getResponse(request);
remote = waitForTask(response).getJsonData();
assertNotNull(remote);
assertEquals(Constants.DEFAULT_REMOTE_NAME, remote.getString(ProtocolConstants.KEY_NAME));
assertNotNull(remote.getString(ProtocolConstants.KEY_LOCATION));
assertEquals(Remote.TYPE, remote.getString(ProtocolConstants.KEY_TYPE));
JSONArray refsArray = remote.getJSONArray(ProtocolConstants.KEY_CHILDREN);
assertEquals(size, refsArray.length());
JSONObject ref = refsArray.getJSONObject(i);
assertEquals(Constants.R_REMOTES + Constants.DEFAULT_REMOTE_NAME + "/" + name, ref.getString(ProtocolConstants.KEY_FULL_NAME));
String newRefId = ref.getString(ProtocolConstants.KEY_ID);
assertTrue(ObjectId.isId(newRefId));
String remoteBranchLocation = ref.getString(ProtocolConstants.KEY_LOCATION);
ref.getString(GitConstants.KEY_COMMIT);
request = GitRemoteTest.getGetGitRemoteRequest(remoteBranchLocation);
response = webConversation.getResponse(request);
JSONObject remoteBranch = waitForTask(response).getJsonData();
assertEquals(RemoteBranch.TYPE, remoteBranch.getString(ProtocolConstants.KEY_TYPE));
assertNotNull(remoteBranch.optString(GitConstants.KEY_COMMIT));
assertNotNull(remoteBranch.optString(GitConstants.KEY_HEAD));
assertNotNull(remoteBranch.optString(GitConstants.KEY_DIFF));
return remoteBranch;
}
protected JSONObject merge(String gitHeadUri, String commit, boolean squash) throws JSONException, IOException, SAXException {
assertCommitUri(gitHeadUri);
WebRequest request = getPostGitMergeRequest(gitHeadUri, commit, squash);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
return new JSONObject(response.getText());
}
protected JSONObject merge(String gitHeadUri, String commit) throws JSONException, IOException, SAXException {
return merge(gitHeadUri, commit, false);
}
// rebase
protected JSONObject rebase(String gitHeadUri, Operation operation) throws IOException, SAXException, JSONException {
assertCommitUri(gitHeadUri);
WebRequest request = GitRebaseTest.getPostGitRebaseRequest(gitHeadUri, "", operation);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
return new JSONObject(response.getText());
}
protected JSONObject rebase(String gitHeadUri, String commit) throws IOException, SAXException, JSONException {
assertCommitUri(gitHeadUri);
WebRequest request = GitRebaseTest.getPostGitRebaseRequest(gitHeadUri, commit, null);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
return new JSONObject(response.getText());
}
// push
protected ServerStatus push(String gitRemoteUri, int size, int i, String name, String srcRef, boolean tags) throws IOException, SAXException, JSONException {
return push(gitRemoteUri, size, i, name, srcRef, tags, false);
}
protected ServerStatus push(String gitRemoteUri, int size, int i, String name, String srcRef, boolean tags, boolean force) throws IOException, SAXException, JSONException {
assertRemoteUri(gitRemoteUri);
String remoteBranchLocation = getRemoteBranch(gitRemoteUri, size, i, name).getString(ProtocolConstants.KEY_LOCATION);
return push(remoteBranchLocation, srcRef, tags, force);
}
/**
* Pushes the changes from the the source ref to the given remote branch.
*
* @param gitRemoteBranchUri remote branch URI
* @param srcRef the source ref to push
* @param tags <code>true</code> to push tags
* @return JSON object representing response
* @throws IOException
* @throws SAXException
* @throws JSONException
*/
protected ServerStatus push(String gitRemoteBranchUri, String srcRef, boolean tags) throws IOException, SAXException, JSONException {
return push(gitRemoteBranchUri, srcRef, tags, false);
}
/**
* Pushes the changes from the the source ref to the given remote branch.
*
* @param gitRemoteBranchUri remote branch URI
* @param srcRef the source ref to push
* @param tags <code>true</code> to push tags
* @param force <code>true</code> to force push
* @return JSON object representing response
* @throws IOException
* @throws SAXException
* @throws JSONException
*/
protected ServerStatus push(String gitRemoteBranchUri, String srcRef, boolean tags, boolean force) throws IOException, SAXException, JSONException {
assertRemoteOrRemoteBranchLocation(gitRemoteBranchUri);
WebRequest request = GitPushTest.getPostGitRemoteRequest(gitRemoteBranchUri, srcRef, tags, force);
ServerStatus status = waitForTask(webConversation.getResponse(request));
return status;
}
protected ServerStatus push(String gitRemoteUri, int size, int i, String name, String srcRef, boolean tags, String userName, String kh, byte[] privk, byte[] pubk, byte[] p, boolean shouldBeOK) throws IOException, SAXException, JSONException {
return push(gitRemoteUri, size, i, name, srcRef, tags, false, userName, kh, privk, pubk, p, shouldBeOK);
}
protected ServerStatus push(String gitRemoteUri, int size, int i, String name, String srcRef, boolean tags, boolean force, String userName, String kh, byte[] privk, byte[] pubk, byte[] p, boolean shouldBeOK) throws IOException, SAXException, JSONException {
assertRemoteUri(gitRemoteUri);
String remoteBranchLocation = getRemoteBranch(gitRemoteUri, size, i, name).getString(ProtocolConstants.KEY_LOCATION);
WebRequest request = GitPushTest.getPostGitRemoteRequest(remoteBranchLocation, srcRef, tags, force, userName, kh, privk, pubk, p);
WebResponse response = webConversation.getResponse(request);
ServerStatus status = waitForTask(response);
if (shouldBeOK) {
assertTrue(status.toString(), status.isOK());
}
return status;
}
/**
* Fetch objects and refs from the given remote branch.
*
* @param remoteBranchLocation remote branch URI
* @return JSONObject representing remote branch after the fetch is done
* @throws JSONException
* @throws IOException
* @throws SAXException
*/
protected JSONObject fetch(String remoteBranchLocation, String userName, String kh, byte[] privk, byte[] pubk, byte[] p, boolean shouldBeOK) throws JSONException, IOException, SAXException {
return fetch(remoteBranchLocation, false, userName, kh, privk, pubk, p, shouldBeOK);
}
/**
* Fetch objects and refs from the given remote branch.
*
* @param remoteBranchLocation remote branch URI
* @param force <code>true</code> to force fetch
* @return JSONObject representing remote branch after the fetch is done
* @throws JSONException
* @throws IOException
* @throws SAXException
*/
protected JSONObject fetch(String remoteBranchLocation, boolean force, String userName, String kh, byte[] privk, byte[] pubk, byte[] p, boolean shouldBeOK) throws JSONException, IOException, SAXException {
assertRemoteOrRemoteBranchLocation(remoteBranchLocation);
// fetch
WebRequest request = GitFetchTest.getPostGitRemoteRequest(remoteBranchLocation, true, force, userName, kh, privk, pubk, p);
WebResponse response = webConversation.getResponse(request);
ServerStatus status = waitForTask(response);
if (shouldBeOK) {
assertTrue(status.toString(), status.isOK());
}
// get remote branch details again
request = GitRemoteTest.getGetGitRemoteRequest(remoteBranchLocation);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
return new JSONObject(response.getText());
}
/**
* Fetch objects and refs from the given remote or remote branch.
*
* @param remoteLocation remote (branch) URI
* @return JSONObject representing remote (branch) after the fetch is done
* @throws JSONException
* @throws IOException
* @throws SAXException
*/
protected JSONObject fetch(String remoteLocation) throws JSONException, IOException, SAXException {
return fetch(remoteLocation, false);
}
/**
* Fetch objects and refs from the given remote or remote branch.
*
* @param remoteLocation remote (branch) URI
* @param force <code>true</code> to force fetch
* @return JSONObject representing remote (branch) after the fetch is done
* @throws JSONException
* @throws IOException
* @throws SAXException
*/
protected JSONObject fetch(String remoteLocation, boolean force) throws JSONException, IOException, SAXException {
assertRemoteOrRemoteBranchLocation(remoteLocation);
// fetch
WebRequest request = GitFetchTest.getPostGitRemoteRequest(remoteLocation, true, force);
ServerStatus status = waitForTask(webConversation.getResponse(request));
assertTrue(status.toString(), status.isOK());
// get remote (branch) details again
request = GitRemoteTest.getGetGitRemoteRequest(remoteLocation);
status = waitForTask(webConversation.getResponse(request));
assertTrue(status.toString(), status.isOK());
return status.getJsonData();
}
/**
* Pulls objects and refs for the given repository and merges them into the current branch.
*
* @param cloneLocation clone URI
* @return status object
* @throws JSONException
* @throws IOException
* @throws SAXException
* @throws CoreException
*/
protected JSONObject pull(String cloneLocation) throws JSONException, IOException, SAXException, CoreException {
assertCloneUri(cloneLocation);
// pull
WebRequest request = GitPullTest.getPostGitRemoteRequest(cloneLocation, false);
ServerStatus status = waitForTask(webConversation.getResponse(request));
assertTrue(status.toString(), status.isOK());
return status.getJsonData();
}
// tag
/**
* Tag the commit with given tag name
*
* @param gitTagUri tags URI
* @param tagName tag name to use
* @param commitId commit to tag
* @return created tag object
* @throws JSONException
* @throws IOException
* @throws SAXException
* @throws URISyntaxException
*/
protected JSONObject tag(String gitTagUri, String tagName, String commitId) throws JSONException, IOException, SAXException, URISyntaxException {
assertTagListUri(gitTagUri);
WebRequest request = getPostGitTagRequest(gitTagUri, tagName, commitId);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
return new JSONObject(response.getText());
}
/**
* Tag the selected commit with the given name.
*
* @param gitCommitUri selected commit URI
* @param tagName tag name to use
* @return an updated commit object
* @throws JSONException
* @throws IOException
* @throws SAXException
*/
protected JSONObject tag(String gitCommitUri, String tagName) throws JSONException, IOException, SAXException {
assertCommitUri(gitCommitUri);
WebRequest request = getPutGitCommitRequest(gitCommitUri, tagName);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
return new JSONObject(response.getText());
}
protected JSONArray listTags(String gitTagUri) throws IOException, SAXException, JSONException {
assertTagListUri(gitTagUri);
WebRequest request = getGetGitTagRequest(gitTagUri);
WebResponse response = webConversation.getResponse(request);
ServerStatus status = waitForTask(response);
assertTrue(status.toString(), status.isOK());
JSONObject tags = status.getJsonData();
assertEquals(Tag.TYPE, tags.getString(ProtocolConstants.KEY_TYPE));
return tags.getJSONArray(ProtocolConstants.KEY_CHILDREN);
}
protected void deleteTag(String gitTagUri) throws IOException, SAXException {
assertTagUri(gitTagUri);
WebRequest request = getDeleteGitTagRequest(gitTagUri);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
}
protected WebResponse checkoutTag(String cloneLocation, String tagName) throws JSONException, IOException, SAXException {
String requestURI = toAbsoluteURI(cloneLocation);
JSONObject body = new JSONObject();
body.put(GitConstants.KEY_TAG_NAME, tagName);
// checkout the tag into a new local branch
// TODO: temporary workaround, JGit fails to checkout a new branch named as the tag
body.put(GitConstants.KEY_BRANCH_NAME, "tag_" + tagName);
WebRequest request = new PutMethodWebRequest(requestURI, IOUtilities.toInputStream(body.toString()), "UTF-8");
request.setHeaderField(ProtocolConstants.HEADER_ORION_VERSION, "1");
setAuthentication(request);
return webConversation.getResponse(request);
}
protected WebResponse getPostGitBlame(String blameUri, String commitId) throws JSONException, IOException, SAXException {
assertBlameUri(blameUri);
String requestURI = toAbsoluteURI(blameUri);
JSONObject body = new JSONObject();
body.put(GitConstants.KEY_COMMIT, commitId);
WebRequest request = new PutMethodWebRequest(requestURI, IOUtilities.toInputStream(body.toString()), "application/json");
request.setHeaderField(ProtocolConstants.HEADER_ORION_VERSION, "1");
setAuthentication(request);
return webConversation.getResponse(request);
}
protected WebResponse getGetGitBlame(String blameUri) throws IOException, SAXException {
assertBlameUri(blameUri);
String requestURI = toAbsoluteURI(blameUri);
WebRequest request = new GetMethodWebRequest(requestURI);
request.setHeaderField(ProtocolConstants.HEADER_ORION_VERSION, "1");
setAuthentication(request);
return webConversation.getResponse(request);
}
/**
* Return commits for the given URI.
*
* @param gitCommitUri commit URI
* @return
* @throws IOException
* @throws SAXException
* @throws JSONException
*/
protected JSONArray log(String gitCommitUri) throws IOException, SAXException, JSONException {
return log(gitCommitUri, null, null, false, false);
}
/**
* Return commits for the given URI.
*
* @param gitCommitUri commit URI
* @param page number of page or <code>null</code> if all results
* @param pageSize size of page or <code>null</code> if default
* @return
* @throws IOException
* @throws SAXException
* @throws JSONException
*/
private JSONObject logObject(String gitCommitUri, Integer page, Integer pageSize) throws IOException, SAXException, JSONException {
assertCommitUri(gitCommitUri);
WebRequest request = GitCommitTest.getGetGitCommitRequest(gitCommitUri, false, page, pageSize);
setAuthentication(request);
WebResponse response = webConversation.getResponse(request);
ServerStatus status = waitForTask(response);
assertTrue(status.toString(), status.isOK());
return status.getJsonData();
}
protected JSONArray log(String gitCommitUri, Integer page, Integer pageSize, boolean prevPage, boolean nextPage) throws IOException, SAXException, JSONException {
JSONObject logObject = logObject(gitCommitUri, page, pageSize);
assertEquals(prevPage, logObject.has(ProtocolConstants.KEY_PREVIOUS_LOCATION));
assertEquals(nextPage, logObject.has(ProtocolConstants.KEY_NEXT_LOCATION));
// see org.eclipse.orion.server.git.objects.Log.getType()
assertEquals(Commit.TYPE, logObject.getString(ProtocolConstants.KEY_TYPE));
return logObject.getJSONArray(ProtocolConstants.KEY_CHILDREN);
}
protected JSONObject logObject(String gitCommitUri) throws IOException, SAXException, JSONException {
return logObject(gitCommitUri, null, null);
}
protected WebResponse branch(String branchesLocation, String branchName) throws IOException, JSONException, SAXException {
return branch(branchesLocation, branchName, null);
}
// branch
protected WebResponse branch(String branchesLocation, String branchName, String startPoint) throws IOException, JSONException, SAXException {
assertBranchUri(branchesLocation);
WebRequest request = getPostGitBranchRequest(branchesLocation, branchName, startPoint);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_CREATED, response.getResponseCode());
return response;
}
static void assertBranchExist(Git git, String branch) throws GitAPIException {
List<Ref> list = git.branchList().call();
for (Ref ref : list) {
if (ref.getName().equals(Constants.R_HEADS + branch)) {
return; // found
}
}
fail("branch '" + branch + "' doesn't exist locally");
}
protected WebResponse checkoutBranch(String cloneLocation, String branchName) throws JSONException, IOException, SAXException {
String requestURI = toAbsoluteURI(cloneLocation);
JSONObject body = new JSONObject();
body.put(GitConstants.KEY_BRANCH_NAME, branchName);
WebRequest request = new PutMethodWebRequest(requestURI, IOUtilities.toInputStream(body.toString()), "UTF-8");
request.setHeaderField(ProtocolConstants.HEADER_ORION_VERSION, "1");
setAuthentication(request);
return webConversation.getResponse(request);
}
JSONObject listBranches(final String branchesLocation) throws IOException, SAXException, JSONException {
WebRequest request = getGetRequest(branchesLocation);
WebResponse response = webConversation.getResponse(request);
ServerStatus status = waitForTask(response);
assertTrue(status.toString(), status.isOK());
JSONObject branches = status.getJsonData();
assertEquals(Branch.TYPE, branches.getString(ProtocolConstants.KEY_TYPE));
return branches;
}
protected String getWorkspaceId(URI uri) throws IOException, SAXException, JSONException {
assertWorkspaceUri(uri);
WebRequest request = new GetMethodWebRequest(uri.toString());
request.setHeaderField(ProtocolConstants.HEADER_ORION_VERSION, "1");
setAuthentication(request);
WebResponse response = webConversation.getResponse(request);
JSONObject workspace = new JSONObject(response.getText());
return workspace.getString(ProtocolConstants.KEY_ID);
}
// assertions for URIs
private static void assertRemoteUri(String remoteUri) {
URI uri = URI.create(toRelativeURI(remoteUri));
IPath path = new Path(uri.getPath());
// /git/remote/file/{path}
assertTrue(path.segmentCount() > 3);
assertEquals(GitServlet.GIT_URI.substring(1), path.segment(0));
assertEquals(Remote.RESOURCE, path.segment(1));
assertEquals("file", path.segment(2));
}
protected static void assertCommitUri(String commitUri) {
URI uri = URI.create(toRelativeURI(commitUri));
IPath path = new Path(uri.getPath());
AssertionError error = null;
// /gitapi/commit/{ref}/file/{path}
try {
assertTrue(path.segmentCount() > 4);
assertEquals(GitServlet.GIT_URI.substring(1), path.segment(0));
assertEquals(Commit.RESOURCE, path.segment(1));
assertEquals("file", path.segment(3));
} catch (AssertionError e) {
error = e;
}
// /gitapi/commit/file/{path}
try {
assertTrue(path.segmentCount() > 3);
assertEquals(GitServlet.GIT_URI.substring(1), path.segment(0));
assertEquals(Commit.RESOURCE, path.segment(1));
assertEquals("file", path.segment(2));
} catch (AssertionError e) {
if (error != null) {
throw error; // rethrow the first exception
} // otherwise it's a commit location, ignore this exception
}
}
static void assertStatusUri(String statusUri) {
URI uri = URI.create(toRelativeURI(statusUri));
IPath path = new Path(uri.getPath());
// /git/status/file/{path}
assertTrue(path.segmentCount() > 3);
assertEquals(GitServlet.GIT_URI.substring(1), path.segment(0));
assertEquals(Status.RESOURCE, path.segment(1));
assertEquals("file", path.segment(2));
}
private static void assertRemoteOrRemoteBranchLocation(String remoteLocation) {
URI uri = URI.create(toRelativeURI(remoteLocation));
IPath path = new Path(uri.getPath());
AssertionError error = null;
// /git/remote/{remote}/file/{path}
try {
assertTrue(path.segmentCount() > 4);
assertEquals(GitServlet.GIT_URI.substring(1), path.segment(0));
assertEquals(Remote.RESOURCE, path.segment(1));
assertEquals("file", path.segment(3));
} catch (AssertionError e) {
error = e;
}
// /git/remote/{remote}/{branch}/file/{path}
try {
assertTrue(path.segmentCount() > 5);
assertEquals(GitServlet.GIT_URI.substring(1), path.segment(0));
assertEquals(Remote.RESOURCE, path.segment(1));
assertEquals("file", path.segment(4));
} catch (AssertionError e) {
if (error != null) {
throw error; // rethrow the first exception
} // otherwise it's a remote location, ignore this exception
}
}
private static void assertTagListUri(String tagUri) {
URI uri = URI.create(toRelativeURI(tagUri));
IPath path = new Path(uri.getPath());
// /git/tag/file/{path}
assertTrue(path.segmentCount() > 3);
assertEquals(GitServlet.GIT_URI.substring(1), path.segment(0));
assertEquals(Tag.RESOURCE, path.segment(1));
assertEquals("file", path.segment(2));
}
private static void assertTagUri(String tagUri) {
URI uri = URI.create(toRelativeURI(tagUri));
IPath path = new Path(uri.getPath());
// /git/tag/{tag}/file/{path}
assertTrue(path.segmentCount() > 4);
assertEquals(GitServlet.GIT_URI.substring(1), path.segment(0));
assertEquals(Tag.RESOURCE, path.segment(1));
assertEquals("file", path.segment(3));
}
static void assertCloneUri(String cloneUri) throws CoreException, IOException {
URI uri = URI.create(toRelativeURI(cloneUri));
IPath path = new Path(uri.getPath());
// /git/clone/workspace/{id} or /git/clone/file/{workspaceId}/{projectName}[/{path}]
assertTrue(path.segmentCount() > 3);
assertEquals(GitServlet.GIT_URI.substring(1), path.segment(0));
assertEquals(Clone.RESOURCE, path.segment(1));
assertTrue("workspace".equals(path.segment(2)) || "file".equals(path.segment(2)));
if ("workspace".equals(path.segment(2)))
assertEquals(4, path.segmentCount());
// TODO: check if clone
if ("file".equals(path.segment(2)))
getRepositoryForContentLocation(SERVER_LOCATION + path.removeFirstSegments(2).makeAbsolute());
}
private static void assertWorkspaceUri(URI uri) {
uri = URI.create(toRelativeURI(uri.toString()));
IPath path = new Path(uri.getPath());
// /workspace/{id}
assertTrue(path.segmentCount() == 2);
assertEquals("workspace", path.segment(0));
}
private static void assertFileUri(String fileUri) {
URI uri = URI.create(toRelativeURI(fileUri));
IPath path = new Path(uri.getPath());
// /file/{workspaceId}/{projectName}[/{path}]
assertTrue(path.segmentCount() > 2);
assertEquals("file", path.segment(0));
}
protected static void assertBlameUri(String fileUri) {
URI uri = URI.create(toRelativeURI(fileUri));
IPath path = new Path(uri.getPath());
// /gitapi/commit/{ref}/file/{path}
System.out.println(uri.toString());
assertTrue(path.segmentCount() > 4);
assertEquals(Blame.RESOURCE, path.segment(1));
assertTrue(/*"file".equals(path.segment(2)) || */"file".equals(path.segment(3)));
}
protected static void assertBranchUri(String branchUri) {
URI uri = URI.create(toRelativeURI(branchUri));
IPath path = new Path(uri.getPath());
// /git/branch/[{name}/]file/{path}
assertTrue(path.segmentCount() > 3);
assertEquals(GitServlet.GIT_URI.substring(1), path.segment(0));
assertEquals(GitServlet.GIT_URI.substring(1), path.segment(0));
assertEquals(Branch.RESOURCE, path.segment(1));
assertTrue("file".equals(path.segment(2)) || "file".equals(path.segment(3)));
}
protected static void assertConfigUri(String configUri) {
URI uri = URI.create(toRelativeURI(configUri));
IPath path = new Path(uri.getPath());
// /gitapi/config/[{key}/]clone/file/{id}
assertTrue(path.segmentCount() > 4);
assertEquals(GitServlet.GIT_URI.substring(1), path.segment(0));
assertEquals(ConfigOption.RESOURCE, path.segment(1));
assertTrue(Clone.RESOURCE.equals(path.segment(2)) || Clone.RESOURCE.equals(path.segment(3)));
if (Clone.RESOURCE.equals(path.segment(2)))
assertTrue("file".equals(path.segment(3)));
else
assertTrue("file".equals(path.segment(4)));
}
protected static void assertGitSectionExists(JSONObject json) {
JSONObject gitSection = json.optJSONObject(GitConstants.KEY_GIT);
assertNotNull(gitSection);
assertNotNull(gitSection.optString(GitConstants.KEY_STATUS, null));
assertNotNull(gitSection.optString(GitConstants.KEY_DIFF, null));
assertNotNull(gitSection.optString(GitConstants.KEY_INDEX, null));
assertNotNull(gitSection.optString(GitConstants.KEY_HEAD, null));
assertNotNull(gitSection.optString(GitConstants.KEY_REMOTE, null));
assertNotNull(gitSection.optString(GitConstants.KEY_TAG, null));
assertNotNull(gitSection.optString(GitConstants.KEY_CLONE, null));
}
// web requests
/**
* Creates a request to create a git clone for the given URI.
* @param uri Git URL to clone
* @param workspacePath workspace path (/workspace/{workspaceId}), required when no filePath is given
* @param filePath project/folder path
* @param name new project name
* @param kh known hosts
* @param p password
* @return the request
* @throws JSONException
* @throws UnsupportedEncodingException
*/
protected static WebRequest getPostGitCloneRequest(URIish uri, IPath workspacePath, IPath filePath, String name, String kh, char[] p) throws JSONException, UnsupportedEncodingException {
WebRequest request = new PostGitCloneRequest().setURIish(uri).setWorkspacePath(workspacePath).setFilePath(filePath).setName(name).setKnownHosts(kh).setPassword(p).getWebRequest();
setAuthentication(request);
return request;
}
private static WebRequest getPostGitMergeRequest(String location, String commit, boolean squash) throws JSONException, UnsupportedEncodingException {
String requestURI = toAbsoluteURI(location);
JSONObject body = new JSONObject();
body.put(GitConstants.KEY_MERGE, commit);
body.put(GitConstants.KEY_SQUASH, squash);
WebRequest request = new PostMethodWebRequest(requestURI, IOUtilities.toInputStream(body.toString()), "UTF-8");
request.setHeaderField(ProtocolConstants.HEADER_ORION_VERSION, "1");
setAuthentication(request);
return request;
}
protected static WebRequest getPostGitTagRequest(String location, String tagName, String commitId) throws JSONException, UnsupportedEncodingException {
assertTagListUri(location);
String requestURI = toAbsoluteURI(location);
JSONObject body = new JSONObject();
body.put(ProtocolConstants.KEY_NAME, tagName);
body.put(GitConstants.KEY_TAG_COMMIT, commitId);
WebRequest request = new PostMethodWebRequest(requestURI, IOUtilities.toInputStream(body.toString()), "application/json");
request.setHeaderField(ProtocolConstants.HEADER_ORION_VERSION, "1");
setAuthentication(request);
return request;
}
protected static WebRequest getPutGitCommitRequest(String location, String tagName) throws UnsupportedEncodingException, JSONException {
String requestURI = toAbsoluteURI(location);
JSONObject body = new JSONObject();
body.put(ProtocolConstants.KEY_NAME, tagName);
WebRequest request = new PutMethodWebRequest(requestURI, IOUtilities.toInputStream(body.toString()), "application/json");
request.setHeaderField(ProtocolConstants.HEADER_ORION_VERSION, "1");
setAuthentication(request);
return request;
}
protected static WebRequest getGetGitTagRequest(String location) {
String requestURI = toAbsoluteURI(location);
WebRequest request = new GetMethodWebRequest(requestURI);
request.setHeaderField(ProtocolConstants.HEADER_ORION_VERSION, "1");
setAuthentication(request);
return request;
}
private static WebRequest getDeleteGitTagRequest(String location) {
String requestURI = toAbsoluteURI(location);
WebRequest request = new DeleteMethodWebRequest(requestURI);
request.setHeaderField(ProtocolConstants.HEADER_ORION_VERSION, "1");
setAuthentication(request);
return request;
}
private WebRequest getPostGitBranchRequest(String location, String branchName, String startPoint) throws IOException, JSONException {
String requestURI = toAbsoluteURI(location);
JSONObject body = new JSONObject();
body.put(ProtocolConstants.KEY_NAME, branchName);
body.put(GitConstants.KEY_BRANCH_NAME, startPoint);
WebRequest request = new PostMethodWebRequest(requestURI, IOUtilities.toInputStream(body.toString()), "UTF-8");
request.setHeaderField(ProtocolConstants.HEADER_ORION_VERSION, "1");
setAuthentication(request);
return request;
}
protected String clone(WebRequest request) throws JSONException, IOException, SAXException {
WebResponse response = webConversation.getResponse(request);
ServerStatus status = waitForTask(webConversation.getResponse(request));
assertTrue(status.toString(), status.isOK());
String cloneLocation = status.getJsonData().getString(ProtocolConstants.KEY_LOCATION);
assertNotNull(cloneLocation);
// validate the clone metadata
response = webConversation.getResponse(getGetRequest(cloneLocation));
JSONObject clones = new JSONObject(response.getText());
JSONArray clonesArray = clones.getJSONArray(ProtocolConstants.KEY_CHILDREN);
assertEquals(1, clonesArray.length());
JSONObject clone = clonesArray.getJSONObject(0);
String contentLocation = clone.getString(ProtocolConstants.KEY_CONTENT_LOCATION);
assertNotNull(contentLocation);
return contentLocation;
}
// Utility methods
protected static String loadFileContents(String path) throws IOException {
File file = new File(path);
InputStream is = new FileInputStream(file);
return toString(is);
}
private static String toString(InputStream is) throws IOException {
if (is != null) {
Writer writer = new StringWriter();
char[] buffer = new char[1024];
try {
Reader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
int n;
while ((n = reader.read(buffer)) != -1) {
writer.write(buffer, 0, n);
}
} finally {
is.close();
}
return writer.toString();
}
return "";
}
protected void assertRepositoryInfo(URIish uri, JSONObject result) throws JSONException {
assertEquals(uri.toString(), result.getJSONObject("JsonData").get("Url"));
if (uri.getUser() != null)
assertEquals(uri.getUser(), result.getJSONObject("JsonData").get("User"));
if (uri.getHost() != null)
assertEquals(uri.getHost(), result.getJSONObject("JsonData").get("Host"));
if (uri.getHumanishName() != null)
assertEquals(uri.getHumanishName(), result.getJSONObject("JsonData").get("HumanishName"));
if (uri.getPass() != null)
assertEquals(uri.getPass(), result.getJSONObject("JsonData").get("Password"));
if (uri.getPort() > 0)
assertEquals(uri.getPort(), result.getJSONObject("JsonData").get("Port"));
if (uri.getScheme() != null)
assertEquals(uri.getScheme(), result.getJSONObject("JsonData").get("Scheme"));
}
protected JSONObject getChild(JSONObject folderObject, String childName) throws JSONException, IOException, SAXException {
String folderChildrenLocation = folderObject.optString(ProtocolConstants.KEY_CHILDREN_LOCATION, null);
if (folderChildrenLocation == null) {
// folderObject is not a folder, but a newly created project
folderObject.getString(ProtocolConstants.KEY_ID);
String projectContentLocation = folderObject.getString(ProtocolConstants.KEY_CONTENT_LOCATION);
WebRequest request = getGetRequest(projectContentLocation);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject folder = new JSONObject(response.getText());
folderChildrenLocation = folder.getString(ProtocolConstants.KEY_CHILDREN_LOCATION);
}
WebRequest request = getGetRequest(folderChildrenLocation);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
List<JSONObject> children = getDirectoryChildren(new JSONObject(response.getText()));
JSONObject child = getChildByName(children, childName);
return child;
}
protected void modifyFile(JSONObject fileObject, String content) throws JSONException, IOException, SAXException {
String fileLocation = fileObject.getString(ProtocolConstants.KEY_LOCATION);
WebRequest request = getPutFileRequest(fileLocation, content);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
}
protected void deleteFile(JSONObject fileObject) throws JSONException, IOException, SAXException {
String fileLocation = fileObject.getString(ProtocolConstants.KEY_LOCATION);
WebRequest request = getDeleteFilesRequest(fileLocation);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
}
protected void addFile(JSONObject... fileObject) throws JSONException, IOException, SAXException {
WebRequest request = null;
if (fileObject.length == 1) {
JSONObject fileGitSection = fileObject[0].getJSONObject(GitConstants.KEY_GIT);
String fileGitIndexUri = fileGitSection.getString(GitConstants.KEY_INDEX);
request = GitAddTest.getPutGitIndexRequest(fileGitIndexUri, null);
} else {
JSONObject fileGitSection = fileObject[0].getJSONObject(GitConstants.KEY_GIT);
String gitCloneUri = fileGitSection.getString(GitConstants.KEY_CLONE);
IPath gitCloneFilePath = new Path(URI.create(toRelativeURI(gitCloneUri)).getPath()).removeFirstSegments(2);
JSONObject clone = getCloneForGitResource(fileObject[0]);
String gitIndexUri = clone.getString(GitConstants.KEY_INDEX);
Set<String> patterns = new HashSet<String>(fileObject.length);
for (int i = 0; i < fileObject.length; i++) {
IPath locationPath = new Path(URI.create(toRelativeURI(fileObject[i].getString(ProtocolConstants.KEY_LOCATION))).getPath());
patterns.add(locationPath.makeRelativeTo(gitCloneFilePath).toString());
}
request = GitAddTest.getPutGitIndexRequest(gitIndexUri, patterns);
}
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
}
protected JSONObject commitFile(JSONObject fileObject, String message) throws JSONException, IOException, SAXException {
WebResponse response = commitFile(fileObject, message, false);
return new JSONObject(response.getText());
}
protected WebResponse commitFile(JSONObject fileObject, String message, boolean amend) throws JSONException, IOException, SAXException {
JSONObject fileGitSection = fileObject.getJSONObject(GitConstants.KEY_GIT);
String fileGitHeadUri = fileGitSection.getString(GitConstants.KEY_HEAD);
WebRequest request = GitCommitTest.getPostGitCommitRequest(fileGitHeadUri, message, amend);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
return response;
}
protected String getFileContent(JSONObject fileObject) throws JSONException, IOException, SAXException {
String location = fileObject.getString(ProtocolConstants.KEY_LOCATION);
assertNotNull(location);
WebRequest request = getGetRequest(location);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
return response.getText();
}
protected String getCommitContent(JSONObject commitObject) throws JSONException, IOException, SAXException {
String contentLocation = commitObject.getString(ProtocolConstants.KEY_CONTENT_LOCATION);
assertNotNull(contentLocation);
WebRequest request = getGetRequest(contentLocation);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
return response.getText();
}
protected JSONObject assertStatus(StatusResult expected, String statusUri) throws IOException, SAXException, JSONException {
assertStatusUri(statusUri);
WebRequest request = getGetGitStatusRequest(statusUri);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject statusResponse = new JSONObject(response.getText());
JSONArray statusArray = statusResponse.getJSONArray(GitConstants.KEY_STATUS_ADDED);
assertEquals(expected.getAdded(), statusArray.length());
if (expected.getAddedNames() != null) {
for (int i = 0; i < expected.getAddedNames().length; i++) {
JSONObject child = statusArray.getJSONObject(i);
assertEquals(expected.getAddedNames()[i], child.getString(ProtocolConstants.KEY_NAME));
if (expected.getAddedLogLengths() != null) {
JSONObject gitSection = child.getJSONObject(GitConstants.KEY_GIT);
gitSection = statusArray.getJSONObject(0).getJSONObject(GitConstants.KEY_GIT);
String gitCommitUri = gitSection.getString(GitConstants.KEY_COMMIT);
JSONArray log = log(gitCommitUri);
assertEquals(expected.getAddedLogLengths()[i], log.length());
}
}
}
statusArray = statusResponse.getJSONArray(GitConstants.KEY_STATUS_CHANGED);
assertEquals(expected.getChanged(), statusArray.length());
if (expected.getChangedNames() != null) {
for (int i = 0; i < expected.getChangedNames().length; i++) {
JSONObject child = statusArray.getJSONObject(i);
assertEquals(expected.getChangedNames()[i], child.getString(ProtocolConstants.KEY_NAME));
if (expected.getChangedContents() != null) {
assertEquals("Invalid file content", expected.getChangedContents()[i], getFileContent(child));
}
if (expected.getChangedDiffs() != null) {
JSONObject gitSection = child.getJSONObject(GitConstants.KEY_GIT);
String gitDiffUri = gitSection.getString(GitConstants.KEY_DIFF);
String[] parts = GitDiffTest.getDiff(gitDiffUri);
assertEquals("Invalid diff content", expected.getChangedDiffs()[i], parts[1]);
}
if (expected.getChangedIndexContents() != null) {
JSONObject gitSection = child.getJSONObject(GitConstants.KEY_GIT);
String gitIndexUri = gitSection.getString(GitConstants.KEY_INDEX);
request = GitIndexTest.getGetGitIndexRequest(gitIndexUri);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
assertEquals("Invalid index content", expected.getChangedIndexContents()[i], response.getText());
}
if (expected.getChangedHeadContents() != null) {
JSONObject gitSection = child.getJSONObject(GitConstants.KEY_GIT);
String commit = gitSection.getString(GitConstants.KEY_COMMIT);
request = GitCommitTest.getGetGitCommitRequest(commit, true);
response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
assertEquals("Invalid head content", expected.getChangedHeadContents()[i], response.getText());
}
if (expected.getChangedLogLengths() != null) {
JSONObject gitSection = child.getJSONObject(GitConstants.KEY_GIT);
gitSection = statusArray.getJSONObject(0).getJSONObject(GitConstants.KEY_GIT);
String gitCommitUri = gitSection.getString(GitConstants.KEY_COMMIT);
JSONArray log = log(gitCommitUri);
assertEquals(expected.getChangedLogLengths()[i], log.length());
}
}
}
statusArray = statusResponse.getJSONArray(GitConstants.KEY_STATUS_CONFLICTING);
assertEquals(expected.getConflicting(), statusArray.length());
if (expected.getConflictingNames() != null) {
for (int i = 0; i < expected.getConflictingNames().length; i++) {
assertEquals(expected.getConflictingNames()[i], statusArray.getJSONObject(i).getString(ProtocolConstants.KEY_NAME));
}
}
statusArray = statusResponse.getJSONArray(GitConstants.KEY_STATUS_MISSING);
assertEquals(expected.getMissing(), statusArray.length());
if (expected.getMissingNames() != null) {
for (int i = 0; i < expected.getMissingNames().length; i++) {
JSONObject child = statusArray.getJSONObject(i);
assertEquals(expected.getMissingNames()[i], child.getString(ProtocolConstants.KEY_NAME));
if (expected.getMissingLogLengths() != null) {
JSONObject gitSection = child.getJSONObject(GitConstants.KEY_GIT);
gitSection = statusArray.getJSONObject(0).getJSONObject(GitConstants.KEY_GIT);
String gitCommitUri = gitSection.getString(GitConstants.KEY_COMMIT);
JSONArray log = log(gitCommitUri);
assertEquals(expected.getMissingLogLengths()[i], log.length());
}
}
}
statusArray = statusResponse.getJSONArray(GitConstants.KEY_STATUS_MODIFIED);
assertEquals(expected.getModified(), statusArray.length());
if (expected.getModifiedNames() != null) {
for (int i = 0; i < expected.getModifiedNames().length; i++) {
JSONObject child = statusArray.getJSONObject(i);
assertEquals(expected.getModifiedNames()[i], child.getString(ProtocolConstants.KEY_NAME));
if (expected.getModifiedContents() != null) {
assertEquals("Invalid file content", expected.getModifiedContents()[i], getFileContent(child));
}
if (expected.getModifiedDiffs() != null) {
JSONObject gitSection = child.getJSONObject(GitConstants.KEY_GIT);
String gitDiffUri = gitSection.getString(GitConstants.KEY_DIFF);
String[] parts = GitDiffTest.getDiff(gitDiffUri);
assertEquals("Invalid diff content", expected.getModifiedDiffs()[i], parts[1]);
}
if (expected.getModifiedLogLengths() != null) {
JSONObject gitSection = child.getJSONObject(GitConstants.KEY_GIT);
gitSection = statusArray.getJSONObject(0).getJSONObject(GitConstants.KEY_GIT);
String gitCommitUri = gitSection.getString(GitConstants.KEY_COMMIT);
JSONArray log = log(gitCommitUri);
assertEquals(expected.getModifiedLogLengths()[i], log.length());
}
}
}
if (expected.getModifiedPaths() != null) {
for (int i = 0; i < expected.getModifiedPaths().length; i++) {
assertEquals(expected.getModifiedPaths()[i], statusArray.getJSONObject(i).getString(ProtocolConstants.KEY_PATH));
}
}
statusArray = statusResponse.getJSONArray(GitConstants.KEY_STATUS_REMOVED);
assertEquals(expected.getRemoved(), statusArray.length());
if (expected.getRemovedNames() != null) {
for (int i = 0; i < expected.getRemovedNames().length; i++) {
JSONObject child = statusArray.getJSONObject(i);
assertEquals(expected.getRemovedNames()[i], child.getString(ProtocolConstants.KEY_NAME));
if (expected.getRemovedLogLengths() != null) {
JSONObject gitSection = child.getJSONObject(GitConstants.KEY_GIT);
gitSection = statusArray.getJSONObject(0).getJSONObject(GitConstants.KEY_GIT);
String gitCommitUri = gitSection.getString(GitConstants.KEY_COMMIT);
JSONArray log = log(gitCommitUri);
assertEquals(expected.getRemovedLogLengths()[i], log.length());
}
}
}
statusArray = statusResponse.getJSONArray(GitConstants.KEY_STATUS_UNTRACKED);
assertEquals(expected.getUntracked(), statusArray.length());
if (expected.getUntrackedNames() != null) {
for (int i = 0; i < expected.getUntrackedNames().length; i++) {
JSONObject child = statusArray.getJSONObject(i);
assertEquals(expected.getUntrackedNames()[i], child.getString(ProtocolConstants.KEY_NAME));
if (expected.getUntrackedLogLengths() != null) {
JSONObject gitSection = child.getJSONObject(GitConstants.KEY_GIT);
gitSection = statusArray.getJSONObject(0).getJSONObject(GitConstants.KEY_GIT);
String gitCommitUri = gitSection.getString(GitConstants.KEY_COMMIT);
JSONArray log = log(gitCommitUri);
assertEquals(expected.getUntrackedLogLengths()[i], log.length());
}
}
}
return statusResponse;
}
protected JSONArray listClones(String workspaceId, IPath path) throws JSONException, IOException, SAXException {
WebRequest request = GitCloneTest.listGitClonesRequest(workspaceId, null);
WebResponse response = webConversation.getResponse(request);
assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
JSONObject clones = new JSONObject(response.getText());
assertEquals(Clone.TYPE, clones.getString(ProtocolConstants.KEY_TYPE));
return clones.getJSONArray(ProtocolConstants.KEY_CHILDREN);
}
protected String workspaceIdFromLocation(URI workspaceLocationURI) {
IPath path = new Path(workspaceLocationURI.getPath());
return path.segment(path.segmentCount() - 1);
}
/**
* Helper method to create two test projects for Git clone tests. One
* project will have the clone location at the root, and the other project
* has a clone location in a folder below the root. This method creates
* the projects and returns the path for creating the clones, but does
* not actually create the git clones.
* @throws CoreException
*/
protected IPath[] createTestProjects(URI workspaceLocationURI) throws JSONException, IOException, SAXException, CoreException {
String workspaceId = workspaceIdFromLocation(workspaceLocationURI);
WorkspaceInfo workspace = OrionConfiguration.getMetaStore().readWorkspace(workspaceId);
assertNotNull(workspace);
String name = testName.getMethodName();
JSONObject projectTop = createProjectOrLink(workspaceLocationURI, name.concat("-top"), null);
IPath clonePathTop = getClonePath(workspaceId, projectTop);
JSONObject projectFolder = createProjectOrLink(workspaceLocationURI, name.concat("-folder"), null);
IPath clonePathFolder = getClonePath(workspaceId, projectFolder).append("folder").makeAbsolute();
IPath[] clonePaths = new IPath[] {clonePathTop, clonePathFolder};
return clonePaths;
}
/**
* Creates three pairs of test projects for clone tests. The pairs are as follows:
* - In first pair, both clones are at the project root
* - In second pair, both clones are in folders below the project root
* - In third pair, one clone is at the root and the other clone is within a child folder
*/
protected IPath[][] createTestClonePairs(URI workspaceLocationURI) throws IOException, SAXException, JSONException, CoreException {
String workspaceId = workspaceIdFromLocation(workspaceLocationURI);
WorkspaceInfo workspace = OrionConfiguration.getMetaStore().readWorkspace(workspaceId);
assertNotNull(workspace);
String name = testName.getMethodName();
JSONObject projectTop1 = createProjectOrLink(workspaceLocationURI, name.concat("-top1"), null);
IPath clonePathTop1 = getClonePath(workspaceId, projectTop1);
JSONObject projectTop2 = createProjectOrLink(workspaceLocationURI, name.concat("-top2"), null);
IPath clonePathTop2 = getClonePath(workspaceId, projectTop2);
JSONObject projectFolder1 = createProjectOrLink(workspaceLocationURI, name.concat("-folder1"), null);
IPath clonePathFolder1 = getClonePath(workspaceId, projectFolder1).append("folder1").makeAbsolute();
JSONObject projectFolder2 = createProjectOrLink(workspaceLocationURI, name.concat("-folder2"), null);
IPath clonePathFolder2 = getClonePath(workspaceId, projectFolder2).append("folder2").makeAbsolute();
JSONObject projectTop3 = createProjectOrLink(workspaceLocationURI, name.concat("-top3"), null);
IPath clonePathTop3 = getClonePath(workspaceId, projectTop3);
JSONObject projectFolder3 = createProjectOrLink(workspaceLocationURI, name.concat("-folder3"), null);
IPath clonePathFolder3 = getClonePath(workspaceId, projectFolder3).append("folder1").makeAbsolute();
IPath[] clonePathsTop = new IPath[] {clonePathTop1, clonePathTop2};
IPath[] clonePathsFolder = new IPath[] {clonePathFolder1, clonePathFolder2};
IPath[] clonePathsMixed = new IPath[] {clonePathTop3, clonePathFolder3};
IPath[][] clonePaths = new IPath[][] {clonePathsTop, clonePathsFolder, clonePathsMixed};
return clonePaths;
}
protected IPath createTempDir() throws CoreException {
// get a temporary folder location, do not use /tmp
File workspaceRoot = OrionConfiguration.getRootLocation().toLocalFile(EFS.NONE, null);
File tmpDir = new File(workspaceRoot, SimpleMetaStoreUtil.ARCHIVE);
if (!tmpDir.exists()) {
tmpDir.mkdirs();
}
if (!tmpDir.exists() || !tmpDir.isDirectory()) {
fail("Cannot find the default temporary-file directory: " + tmpDir.toString());
}
// get a temporary folder name
SecureRandom random = new SecureRandom();
long n = random.nextLong();
n = (n == Long.MIN_VALUE) ? 0 : Math.abs(n);
String tmpDirStr = Long.toString(n);
File tempDir = new File(tmpDir, tmpDirStr);
if (!tempDir.mkdir()) {
fail("Cannot create a temporary directory at " + tempDir.toString());
}
return Path.fromOSString(tempDir.toString());
}
}