/******************************************************************************* * Copyright (c) 2011, 2014 IBM Corporation and others * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.orion.server.tests.servlets.git; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.URI; import java.net.URISyntaxException; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.ListBranchCommand.ListMode; 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.RefSpec; import org.eclipse.jgit.transport.RemoteConfig; import org.eclipse.jgit.transport.URIish; import org.eclipse.orion.internal.server.core.metastore.SimpleMetaStore; import org.eclipse.orion.server.core.IOUtilities; import org.eclipse.orion.server.core.ProtocolConstants; import org.eclipse.orion.server.core.ServerStatus; import org.eclipse.orion.server.git.GitConstants; import org.eclipse.orion.server.git.servlets.GitUtils; import org.eclipse.orion.server.tests.servlets.internal.DeleteMethodWebRequest; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.junit.Test; import org.xml.sax.SAXException; import com.meterware.httpunit.GetMethodWebRequest; import com.meterware.httpunit.PostMethodWebRequest; import com.meterware.httpunit.WebRequest; import com.meterware.httpunit.WebResponse; public class GitRemoteTest extends GitTest { @Test public void testGetNoRemote() throws Exception { URI contentLocation = gitDir.toURI(); JSONObject project = linkProject(contentLocation.toString(), getMethodName().concat("Project")); String projectContentLocation = project.getString(ProtocolConstants.KEY_CONTENT_LOCATION); assertNotNull(projectContentLocation); // http://<host>/file/<projectId>/ WebRequest request = getGetRequest(projectContentLocation); 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); request = getGetGitRemoteRequest(gitRemoteUri); response = webConversation.getResponse(request); assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode()); JSONObject remotes = new JSONObject(response.getText()); JSONArray remotesArray = remotes.getJSONArray(ProtocolConstants.KEY_CHILDREN); assertEquals(0, remotesArray.length()); } @Test public void testGetOrigin() throws Exception { createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME); IPath[] clonePaths = createTestProjects(workspaceLocation); for (IPath clonePath : clonePaths) { // clone a repo JSONObject clone = clone(clonePath); String cloneContentLocation = clone.getString(ProtocolConstants.KEY_CONTENT_LOCATION); String gitRemoteUri = clone.getString(GitConstants.KEY_REMOTE); JSONObject remoteBranch = getRemoteBranch(gitRemoteUri, 1, 0, Constants.MASTER); assertNotNull(remoteBranch); // 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()); // check if Git locations are in place JSONObject gitSection = folder.getJSONObject(GitConstants.KEY_GIT); assertEquals(gitRemoteUri, gitSection.getString(GitConstants.KEY_REMOTE)); } } @Test public void testGetUnknownRemote() 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.optJSONObject(GitConstants.KEY_GIT); assertNotNull(gitSection); String gitRemoteUri = gitSection.getString(GitConstants.KEY_REMOTE); request = getGetGitRemoteRequest(gitRemoteUri); 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); String remoteLocation = remote.getString(ProtocolConstants.KEY_LOCATION); assertNotNull(remoteLocation); URI u = URI.create(toRelativeURI(remoteLocation)); IPath p = new Path(u.getPath()); p = p.uptoSegment(2).append("xxx").append(p.removeFirstSegments(3)); URI nu = new URI(u.getScheme(), u.getUserInfo(), u.getHost(), u.getPort(), p.toString(), u.getQuery(), u.getFragment()); request = getGetGitRemoteRequest(nu.toString()); response = webConversation.getResponse(request); ServerStatus status = waitForTask(response); assertEquals(status.toString(), status.getHttpCode(), HttpURLConnection.HTTP_NOT_FOUND); p = new Path(u.getPath()); p = p.uptoSegment(3).append("xxx").append(p.removeFirstSegments(3)); nu = new URI(u.getScheme(), u.getUserInfo(), u.getHost(), u.getPort(), p.toString(), u.getQuery(), u.getFragment()); request = getGetGitRemoteRequest(nu.toString()); response = webConversation.getResponse(request); assertEquals(HttpURLConnection.HTTP_NOT_FOUND, response.getResponseCode()); } @Test public void testGetRemoteCommits() throws Exception { createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME); IPath[] clonePaths = createTestProjects(workspaceLocation); for (IPath clonePath : clonePaths) { // clone a repo JSONObject clone = clone(clonePath); String cloneContentLocation = clone.getString(ProtocolConstants.KEY_CONTENT_LOCATION); // 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()); JSONObject gitSection = folder.getJSONObject(GitConstants.KEY_GIT); String gitRemoteUri = gitSection.getString(GitConstants.KEY_REMOTE); String gitIndexUri = gitSection.getString(GitConstants.KEY_INDEX); String gitHeadUri = gitSection.getString(GitConstants.KEY_HEAD); JSONObject remoteBranch = getRemoteBranch(gitRemoteUri, 1, 0, Constants.MASTER); assertNotNull(remoteBranch); String remoteBranchLocation = remoteBranch.getString(ProtocolConstants.KEY_LOCATION); request = getGetGitRemoteRequest(remoteBranchLocation); response = webConversation.getResponse(request); assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode()); remoteBranch = new JSONObject(response.getText()); String commitLocation = remoteBranch.getString(GitConstants.KEY_COMMIT); JSONArray commitsArray = log(commitLocation); assertEquals(1, commitsArray.length()); // change JSONObject testTxt = getChild(folder, "test.txt"); modifyFile(testTxt, "change"); // add request = GitAddTest.getPutGitIndexRequest(gitIndexUri); response = webConversation.getResponse(request); assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode()); // commit request = GitCommitTest.getPostGitCommitRequest(gitHeadUri, "new change commit", false); response = webConversation.getResponse(request); assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode()); // push ServerStatus pushStatus = push(gitRemoteUri, 1, 0, Constants.MASTER, Constants.HEAD, false); assertEquals(true, pushStatus.isOK()); remoteBranch = getRemoteBranch(gitRemoteUri, 1, 0, Constants.MASTER); assertNotNull(remoteBranch); remoteBranchLocation = remoteBranch.getString(ProtocolConstants.KEY_LOCATION); request = getGetGitRemoteRequest(remoteBranchLocation); response = webConversation.getResponse(request); assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode()); remoteBranch = new JSONObject(response.getText()); commitLocation = remoteBranch.getString(GitConstants.KEY_COMMIT); commitsArray = log(commitLocation); assertEquals(2, commitsArray.length()); // TODO: test pushing change from another repo and fetch here // creating a fresh repo: we push changes during this tests so the repo would be dirty for the next iteration createRepository(); } } @Test public void testGetRemoteBranches() 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); 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 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); Repository db1 = getRepositoryForContentLocation(cloneContentLocation); Git git = Git.wrap(db1); int localBefore = git.branchList().call().size(); int remoteBefore = git.branchList().setListMode(ListMode.REMOTE).call().size(); int allBefore = git.branchList().setListMode(ListMode.ALL).call().size(); branch(branchesLocation, "a"); assertEquals(1, git.branchList().call().size() - localBefore); assertEquals(0, git.branchList().setListMode(ListMode.REMOTE).call().size() - remoteBefore); assertEquals(1, git.branchList().setListMode(ListMode.ALL).call().size() - allBefore); // push all // TODO: replace with REST API when bug 339115 is fixed git.push().setPushAll().call(); assertEquals(1, git.branchList().call().size() - localBefore); assertEquals(1, git.branchList().setListMode(ListMode.REMOTE).call().size() - remoteBefore); assertEquals(2, git.branchList().setListMode(ListMode.ALL).call().size() - allBefore); checkoutBranch(cloneLocation, Constants.MASTER); JSONObject remoteBranch = getRemoteBranch(gitRemoteUri, 2, 0, Constants.MASTER); assertNotNull(remoteBranch); checkoutBranch(cloneLocation, "a"); remoteBranch = getRemoteBranch(gitRemoteUri, 2, 0, "a"); assertNotNull(remoteBranch); } @Test public void testAddRemoveRemote() throws Exception { createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME); String workspaceId = workspaceIdFromLocation(workspaceLocation); JSONObject project = createProjectOrLink(workspaceLocation, getMethodName().concat("Project"), null); IPath clonePath = getClonePath(workspaceId, project); JSONObject clone = clone(clonePath); String remotesLocation = clone.getString(GitConstants.KEY_REMOTE); // expect only origin getRemote(remotesLocation, 1, 0, Constants.DEFAULT_REMOTE_NAME); // create remote WebResponse response = addRemote(remotesLocation, "a", "https://a.b"); String remoteLocation = response.getHeaderField(ProtocolConstants.HEADER_LOCATION); String remoteLocationFromBody = new JSONObject(response.getText()).getString(ProtocolConstants.KEY_LOCATION); assertEquals(remoteLocation, remoteLocationFromBody); // check details WebRequest request = getGetRequest(remoteLocation); response = webConversation.getResponse(request); ServerStatus status = waitForTask(response); assertTrue(status.toString(), status.isOK()); // list remotes request = getGetRequest(remotesLocation); response = webConversation.getResponse(request); status = waitForTask(response); assertTrue(status.toString(), status.isOK()); JSONObject remotes = status.getJsonData(); JSONArray remotesArray = remotes.getJSONArray(ProtocolConstants.KEY_CHILDREN); // expect origin and new remote assertEquals(2, remotesArray.length()); // remove remote request = getDeleteGitRemoteRequest(remoteLocation); response = webConversation.getResponse(request); assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode()); // list remotes again, make sure it's gone request = getGetRequest(remotesLocation); response = webConversation.getResponse(request); status = waitForTask(response); assertTrue(status.toString(), status.isOK()); remotes = status.getJsonData(); remotesArray = remotes.getJSONArray(ProtocolConstants.KEY_CHILDREN); // expect origin only assertEquals(1, remotesArray.length()); getRemote(remotesLocation, 1, 0, Constants.DEFAULT_REMOTE_NAME); } @Test public void testRemoteProperties() throws IOException, SAXException, JSONException, CoreException, URISyntaxException { createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME); String workspaceId = workspaceIdFromLocation(workspaceLocation); JSONObject project = createProjectOrLink(workspaceLocation, getMethodName().concat("Project"), null); IPath clonePath = getClonePath(workspaceId, project); JSONObject clone = clone(clonePath); String remotesLocation = clone.getString(GitConstants.KEY_REMOTE); project.getString(ProtocolConstants.KEY_CONTENT_LOCATION); // create remote final String remoteName = "remote1"; final String remoteUri = "http://remote1.com"; final String fetchRefSpec = "+refs/heads/*:refs/remotes/%s/*"; final String pushUri = "http://remote2.com"; final String pushRefSpec = "refs/heads/*:refs/heads/*"; addRemote(remotesLocation, remoteName, remoteUri, fetchRefSpec, pushUri, pushRefSpec); Repository db2 = FileRepositoryBuilder.create(GitUtils.getGitDir(new Path(toRelativeURI(clonePath.toString())))); toClose.add(db2); StoredConfig config = db2.getConfig(); RemoteConfig rc = new RemoteConfig(config, remoteName); assertNotNull(rc); // main uri assertEquals(1, rc.getURIs().size()); assertEquals(new URIish(remoteUri).toString(), rc.getURIs().get(0).toString()); // fetchRefSpec assertEquals(1, rc.getFetchRefSpecs().size()); assertEquals(new RefSpec(fetchRefSpec), rc.getFetchRefSpecs().get(0)); // pushUri assertEquals(1, rc.getPushURIs().size()); assertEquals(new URIish(pushUri).toString(), rc.getPushURIs().get(0).toString()); // pushRefSpec assertEquals(1, rc.getPushRefSpecs().size()); assertEquals(new RefSpec(pushRefSpec), rc.getPushRefSpecs().get(0)); } static WebRequest getGetGitRemoteRequest(String location) { String requestURI = toAbsoluteURI(location); WebRequest request = new GetMethodWebRequest(requestURI); request.setHeaderField(ProtocolConstants.HEADER_ORION_VERSION, "1"); setAuthentication(request); return request; } static WebRequest getPostGitRemoteRequest(String location, String name, String uri, String fetchRefSpec, String pushUri, String pushRefSpec) throws JSONException, UnsupportedEncodingException { String requestURI = toAbsoluteURI(location); JSONObject body = new JSONObject(); body.put(GitConstants.KEY_REMOTE_NAME, name); body.put(GitConstants.KEY_REMOTE_URI, uri); body.put(GitConstants.KEY_REMOTE_FETCH_REF, fetchRefSpec); body.put(GitConstants.KEY_REMOTE_PUSH_URI, pushUri); body.put(GitConstants.KEY_REMOTE_PUSH_REF, pushRefSpec); WebRequest request = new PostMethodWebRequest(requestURI, IOUtilities.toInputStream(body.toString()), "UTF-8"); request.setHeaderField(ProtocolConstants.HEADER_ORION_VERSION, "1"); setAuthentication(request); return request; } static WebRequest getDeleteGitRemoteRequest(String location) { String requestURI = toAbsoluteURI(location); WebRequest request = new DeleteMethodWebRequest(requestURI); request.setHeaderField(ProtocolConstants.HEADER_ORION_VERSION, "1"); setAuthentication(request); return request; } static void assertOnBranch(Git git, String branch) throws IOException { assertNotNull(git.getRepository().getRef(branch)); } }