summaryrefslogtreecommitdiffstatsabout
diff options
context:
space:
mode:
authorPiotr Janik2011-05-30 11:43:04 (EDT)
committer Szymon Brandys2011-05-30 11:43:04 (EDT)
commit16d348a09e7f3a2c83273e85c6abd46f6b8dfd29 (patch)
tree46d87a7782782b7113f755a644ff1cc80123a449
parentb7ee3a2544368ba9638d81fda1c06346a19c0a0e (diff)
downloadorg.eclipse.orion.server-16d348a09e7f3a2c83273e85c6abd46f6b8dfd29.zip
org.eclipse.orion.server-16d348a09e7f3a2c83273e85c6abd46f6b8dfd29.tar.gz
org.eclipse.orion.server-16d348a09e7f3a2c83273e85c6abd46f6b8dfd29.tar.bz2
bug 345269 - [server] Provide REST API for git init
https://bugs.eclipse.org/bugs/show_bug.cgi?id=345269
-rw-r--r--bundles/org.eclipse.orion.server.git/src/org/eclipse/orion/server/git/servlets/GitCloneHandlerV1.java106
-rw-r--r--tests/org.eclipse.orion.server.tests/src/org/eclipse/orion/server/tests/servlets/git/AllGitTests.java2
-rw-r--r--tests/org.eclipse.orion.server.tests/src/org/eclipse/orion/server/tests/servlets/git/GitCloneTest.java11
-rw-r--r--tests/org.eclipse.orion.server.tests/src/org/eclipse/orion/server/tests/servlets/git/GitInitTest.java99
-rw-r--r--tests/org.eclipse.orion.server.tests/src/org/eclipse/orion/server/tests/servlets/git/GitTest.java29
5 files changed, 201 insertions, 46 deletions
diff --git a/bundles/org.eclipse.orion.server.git/src/org/eclipse/orion/server/git/servlets/GitCloneHandlerV1.java b/bundles/org.eclipse.orion.server.git/src/org/eclipse/orion/server/git/servlets/GitCloneHandlerV1.java
index 3c3ac88..ab6e720 100644
--- a/bundles/org.eclipse.orion.server.git/src/org/eclipse/orion/server/git/servlets/GitCloneHandlerV1.java
+++ b/bundles/org.eclipse.orion.server.git/src/org/eclipse/orion/server/git/servlets/GitCloneHandlerV1.java
@@ -20,8 +20,7 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.core.runtime.*;
-import org.eclipse.jgit.api.CheckoutCommand;
-import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.*;
import org.eclipse.jgit.api.errors.*;
import org.eclipse.jgit.lib.*;
import org.eclipse.jgit.storage.file.FileBasedConfig;
@@ -71,14 +70,22 @@ public class GitCloneHandlerV1 extends ServletResourceHandler<String> {
return false;
}
- private boolean handlePost(HttpServletRequest request, HttpServletResponse response) throws IOException, JSONException, ServletException, URISyntaxException, CoreException {
+ private boolean handlePost(HttpServletRequest request, HttpServletResponse response) throws IOException, JSONException, ServletException, URISyntaxException, CoreException, NoHeadException, NoMessageException, ConcurrentRefUpdateException, JGitInternalException, WrongRepositoryStateException {
// make sure required fields are set
JSONObject toAdd = OrionServlet.readJSONRequest(request);
WebClone clone = new WebClone();
String url = toAdd.optString(GitConstants.KEY_URL, null);
- if (!validateCloneUrl(url, request, response))
- return true;
- clone.setUrl(new URIish(url));
+ // method handles repository clone or just repository init
+ // decision is based on existence of GitUrl argument
+ boolean initOnly;
+ if (url == null || url.isEmpty())
+ initOnly = true;
+ else {
+ initOnly = false;
+ if (!validateCloneUrl(url, request, response))
+ return true;
+ clone.setUrl(new URIish(url));
+ }
String cloneName = toAdd.optString(ProtocolConstants.KEY_NAME, null);
if (cloneName == null)
cloneName = request.getHeader(ProtocolConstants.HEADER_SLUG);
@@ -90,9 +97,16 @@ public class GitCloneHandlerV1 extends ServletResourceHandler<String> {
String msg = NLS.bind("Either '" + GitConstants.KEY_PATH + "' or '" + GitConstants.KEY_PATH + "' should be provided: {0}", toAdd);
return statusHandler.handleRequest(request, response, new ServerStatus(IStatus.ERROR, HttpServletResponse.SC_BAD_REQUEST, msg, null));
}
+ // only during init operation filePath or cloneName must be provided
+ // during clone operation, name can be obtained from URL
+ if (initOnly && filePath == null && cloneName == null) {
+ String msg = NLS.bind("Either '" + GitConstants.KEY_PATH + "' or '" + GitConstants.KEY_NAME + "' should be provided: {0}", toAdd);
+ return statusHandler.handleRequest(request, response, new ServerStatus(IStatus.ERROR, HttpServletResponse.SC_BAD_REQUEST, msg, null));
+ }
if (!validateCloneName(cloneName, request, response))
return true;
+ // prepare the WebClone object, create a new project if necessary
if (filePath != null) {
IPath path = new Path(filePath);
clone.setId(path.removeFirstSegments(1).toString());
@@ -103,6 +117,7 @@ public class GitCloneHandlerV1 extends ServletResourceHandler<String> {
} else if (workspacePath != null) {
IPath path = new Path(workspacePath);
// TODO: move this to CloneJob
+ // if so, modify init part to create a new project if necessary
String id = WebProject.nextProjectId();
WebProject webProject = WebProject.fromId(id);
if (cloneName == null)
@@ -143,34 +158,57 @@ public class GitCloneHandlerV1 extends ServletResourceHandler<String> {
}
clone.setName(cloneName);
- // prepare creds
- String username = toAdd.optString(GitConstants.KEY_USERNAME, null);
- char[] password = toAdd.optString(GitConstants.KEY_PASSWORD, "").toCharArray(); //$NON-NLS-1$
- String knownHosts = toAdd.optString(GitConstants.KEY_KNOWN_HOSTS, null);
- byte[] privateKey = toAdd.optString(GitConstants.KEY_PRIVATE_KEY, "").getBytes(); //$NON-NLS-1$
- byte[] publicKey = toAdd.optString(GitConstants.KEY_PUBLIC_KEY, "").getBytes(); //$NON-NLS-1$
- byte[] passphrase = toAdd.optString(GitConstants.KEY_PASSPHRASE, "").getBytes(); //$NON-NLS-1$
-
- GitCredentialsProvider cp = new GitCredentialsProvider(new URIish(clone.getUrl()), username, password, knownHosts);
- cp.setPrivateKey(privateKey);
- cp.setPublicKey(publicKey);
- cp.setPassphrase(passphrase);
-
- JSONObject cloneObject = WebClone.toJSON(clone, getURI(request));
- String cloneLocation = cloneObject.getString(ProtocolConstants.KEY_LOCATION);
-
- // if all went well, clone
- CloneJob job = new CloneJob(clone, cp, request.getRemoteUser(), cloneLocation);
- job.schedule();
- TaskInfo task = job.getTask();
- JSONObject result = task.toJSON();
- //Not nice that the git service knows the location of the task servlet, but task service doesn't know this either
- String taskLocation = getURI(request).resolve("../../task/id/" + task.getTaskId()).toString(); //$NON-NLS-1$
- result.put(ProtocolConstants.KEY_LOCATION, taskLocation);
- response.setHeader(ProtocolConstants.HEADER_LOCATION, taskLocation);
- OrionServlet.writeJSONResponse(request, response, result);
- response.setStatus(HttpServletResponse.SC_ACCEPTED);
- return true;
+ if (initOnly) {
+ // git init
+ // call Init using JGit porcelain API
+ InitCommand command = new InitCommand();
+ File directory = new File(clone.getContentLocation());
+ command.setDirectory(directory);
+ Repository repository = command.call().getRepository();
+ Git git = new Git(repository);
+
+ // without initial commit, there are plenty of errors
+ // doing initial commit manually using orion is impossible
+ // workaround:
+ git.commit().setMessage("Initial commit").call();
+
+ JSONObject result = WebClone.toJSON(clone, getURI(request));
+ String cloneLocation = result.getString(ProtocolConstants.KEY_LOCATION);
+ OrionServlet.writeJSONResponse(request, response, result);
+ response.setHeader(ProtocolConstants.HEADER_LOCATION, cloneLocation);
+ response.setStatus(HttpServletResponse.SC_CREATED);
+ return true;
+ } else {
+ // git clone
+ // prepare creds
+ String username = toAdd.optString(GitConstants.KEY_USERNAME, null);
+ char[] password = toAdd.optString(GitConstants.KEY_PASSWORD, "").toCharArray(); //$NON-NLS-1$
+ String knownHosts = toAdd.optString(GitConstants.KEY_KNOWN_HOSTS, null);
+ byte[] privateKey = toAdd.optString(GitConstants.KEY_PRIVATE_KEY, "").getBytes(); //$NON-NLS-1$
+ byte[] publicKey = toAdd.optString(GitConstants.KEY_PUBLIC_KEY, "").getBytes(); //$NON-NLS-1$
+ byte[] passphrase = toAdd.optString(GitConstants.KEY_PASSPHRASE, "").getBytes(); //$NON-NLS-1$
+
+ GitCredentialsProvider cp = new GitCredentialsProvider(new URIish(clone.getUrl()), username, password, knownHosts);
+ cp.setPrivateKey(privateKey);
+ cp.setPublicKey(publicKey);
+ cp.setPassphrase(passphrase);
+
+ JSONObject cloneObject = WebClone.toJSON(clone, getURI(request));
+ String cloneLocation = cloneObject.getString(ProtocolConstants.KEY_LOCATION);
+
+ // if all went well, clone
+ CloneJob job = new CloneJob(clone, cp, request.getRemoteUser(), cloneLocation);
+ job.schedule();
+ TaskInfo task = job.getTask();
+ JSONObject result = task.toJSON();
+ //Not nice that the git service knows the location of the task servlet, but task service doesn't know this either
+ String taskLocation = getURI(request).resolve("../../task/id/" + task.getTaskId()).toString(); //$NON-NLS-1$
+ result.put(ProtocolConstants.KEY_LOCATION, taskLocation);
+ response.setHeader(ProtocolConstants.HEADER_LOCATION, taskLocation);
+ OrionServlet.writeJSONResponse(request, response, result);
+ response.setStatus(HttpServletResponse.SC_ACCEPTED);
+ return true;
+ }
}
private boolean handleGet(HttpServletRequest request, HttpServletResponse response, String pathString) throws IOException, JSONException, ServletException, URISyntaxException, CoreException {
diff --git a/tests/org.eclipse.orion.server.tests/src/org/eclipse/orion/server/tests/servlets/git/AllGitTests.java b/tests/org.eclipse.orion.server.tests/src/org/eclipse/orion/server/tests/servlets/git/AllGitTests.java
index d248a2b..2a8bee9 100644
--- a/tests/org.eclipse.orion.server.tests/src/org/eclipse/orion/server/tests/servlets/git/AllGitTests.java
+++ b/tests/org.eclipse.orion.server.tests/src/org/eclipse/orion/server/tests/servlets/git/AllGitTests.java
@@ -18,7 +18,7 @@ import org.junit.runners.Suite.SuiteClasses;
* Runs all automated server tests for git support.
*/
@RunWith(Suite.class)
-@SuiteClasses({GitUriTest.class, GitCloneTest.class, GitDiffTest.class, GitStatusTest.class, GitIndexTest.class, GitAddTest.class, GitResetTest.class, GitCommitTest.class, GitConfigTest.class, GitRemoteTest.class, GitFetchTest.class, GitMergeTest.class, GitPushTest.class, GitLogTest.class, GitTagTest.class, GitUtilsTest.class, GitCheckoutTest.class, GitBranchTest.class})
+@SuiteClasses({GitUriTest.class, GitCloneTest.class, GitInitTest.class, GitDiffTest.class, GitStatusTest.class, GitIndexTest.class, GitAddTest.class, GitResetTest.class, GitCommitTest.class, GitConfigTest.class, GitRemoteTest.class, GitFetchTest.class, GitMergeTest.class, GitPushTest.class, GitLogTest.class, GitTagTest.class, GitUtilsTest.class, GitCheckoutTest.class, GitBranchTest.class})
public class AllGitTests {
//goofy junit4, no class body needed
}
diff --git a/tests/org.eclipse.orion.server.tests/src/org/eclipse/orion/server/tests/servlets/git/GitCloneTest.java b/tests/org.eclipse.orion.server.tests/src/org/eclipse/orion/server/tests/servlets/git/GitCloneTest.java
index abda9de..2391052 100644
--- a/tests/org.eclipse.orion.server.tests/src/org/eclipse/orion/server/tests/servlets/git/GitCloneTest.java
+++ b/tests/org.eclipse.orion.server.tests/src/org/eclipse/orion/server/tests/servlets/git/GitCloneTest.java
@@ -126,17 +126,6 @@ public class GitCloneTest extends GitTest {
}
@Test
- public void testCloneEmptyUrl() throws Exception {
- URI workspaceLocation = createWorkspace(getMethodName());
- JSONObject project = createProjectOrLink(workspaceLocation, getMethodName(), null);
- IPath clonePath = new Path("file").append(project.getString(ProtocolConstants.KEY_ID)).makeAbsolute();
-
- WebRequest request = getPostGitCloneRequest("", clonePath);
- WebResponse response = webConversation.getResponse(request);
- assertEquals(HttpURLConnection.HTTP_BAD_REQUEST, response.getResponseCode());
- }
-
- @Test
public void testCloneAndCreateProjectByName() throws Exception {
URI workspaceLocation = createWorkspace(getMethodName());
IPath clonePath = new Path("workspace").append(getWorkspaceId(workspaceLocation)).makeAbsolute();
diff --git a/tests/org.eclipse.orion.server.tests/src/org/eclipse/orion/server/tests/servlets/git/GitInitTest.java b/tests/org.eclipse.orion.server.tests/src/org/eclipse/orion/server/tests/servlets/git/GitInitTest.java
new file mode 100644
index 0000000..b1e6310
--- /dev/null
+++ b/tests/org.eclipse.orion.server.tests/src/org/eclipse/orion/server/tests/servlets/git/GitInitTest.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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 java.io.UnsupportedEncodingException;
+import java.net.HttpURLConnection;
+import java.net.URI;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.orion.internal.server.servlets.ProtocolConstants;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.junit.Test;
+
+import com.meterware.httpunit.WebRequest;
+import com.meterware.httpunit.WebResponse;
+
+public class GitInitTest extends GitTest {
+
+ @Test
+ public void testInit() throws Exception {
+ URI workspaceLocation = createWorkspace(getMethodName());
+ JSONObject project = createProjectOrLink(workspaceLocation, getMethodName(), null);
+ IPath initPath = new Path("file").append(project.getString(ProtocolConstants.KEY_ID)).makeAbsolute();
+ String contentLocation = init(null, initPath, null).getString(ProtocolConstants.KEY_CONTENT_LOCATION);
+
+ Repository repository = getRepositoryForContentLocation(contentLocation);
+ assertNotNull(repository);
+ }
+
+ @Test
+ public void testInitAndCreateProjectByName() throws Exception {
+ URI workspaceLocation = createWorkspace(getMethodName());
+ IPath initPath = new Path("workspace").append(getWorkspaceId(workspaceLocation)).makeAbsolute();
+
+ JSONObject repo = init(initPath, null, getMethodName());
+
+ String contentLocation = repo.getString(ProtocolConstants.KEY_CONTENT_LOCATION);
+ WebRequest request = getGetFilesRequest(contentLocation);
+ WebResponse response = webConversation.getResponse(request);
+ assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
+ JSONObject project = new JSONObject(response.getText());
+ assertEquals(getMethodName(), project.getString(ProtocolConstants.KEY_NAME));
+ assertGitSectionExists(project);
+ String childrenLocation = project.getString(ProtocolConstants.KEY_CHILDREN_LOCATION);
+ assertNotNull(childrenLocation);
+
+ // http://<host>/file/<projectId>/?depth=1
+ request = getGetFilesRequest(childrenLocation);
+ response = webConversation.getResponse(request);
+ assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
+ }
+
+ @Test
+ public void testInitAndCreateFolderByPath() throws Exception {
+ URI workspaceLocation = createWorkspace(getMethodName());
+ JSONObject project = createProjectOrLink(workspaceLocation, getMethodName(), null);
+ IPath initPath = new Path("file").append(project.getString(ProtocolConstants.KEY_ID)).append("repos").append("repo1").makeAbsolute();
+
+ // /file/{id}/repos/repo1, folders: 'repo' and 'repo1' don't exist
+ JSONObject repo = init(null, initPath, null);
+
+ String contentLocation = repo.getString(ProtocolConstants.KEY_CONTENT_LOCATION);
+ WebRequest request = getGetFilesRequest(contentLocation);
+ WebResponse response = webConversation.getResponse(request);
+ assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
+ JSONObject folder = new JSONObject(response.getText());
+ assertGitSectionExists(folder);
+ }
+
+ @Test
+ public void testInitWithoutNameAndFilePath() throws Exception {
+ URI workspaceLocation = createWorkspace(getMethodName());
+ JSONObject project = createProjectOrLink(workspaceLocation, getMethodName(), null);
+ IPath initPath = new Path("workspace").append(getWorkspaceId(workspaceLocation)).makeAbsolute();
+
+ WebRequest request = getPostGitInitRequest(initPath, null, null);
+ WebResponse response = webConversation.getResponse(request);
+ assertEquals(HttpURLConnection.HTTP_BAD_REQUEST, response.getResponseCode());
+ }
+
+ private WebRequest getPostGitInitRequest(IPath workspace, IPath path, String name) throws JSONException, UnsupportedEncodingException {
+ return getPostGitCloneRequest(null, workspace, path, name, null, null);
+ }
+
+}
diff --git a/tests/org.eclipse.orion.server.tests/src/org/eclipse/orion/server/tests/servlets/git/GitTest.java b/tests/org.eclipse.orion.server.tests/src/org/eclipse/orion/server/tests/servlets/git/GitTest.java
index 51be79a..1d58286 100644
--- a/tests/org.eclipse.orion.server.tests/src/org/eclipse/orion/server/tests/servlets/git/GitTest.java
+++ b/tests/org.eclipse.orion.server.tests/src/org/eclipse/orion/server/tests/servlets/git/GitTest.java
@@ -338,6 +338,35 @@ public abstract class GitTest extends FileSystemTest {
return clone;
}
+ // init
+
+ protected JSONObject init(IPath workspacePath, IPath filePath, String name) throws JSONException, IOException, SAXException, CoreException {
+ // clone
+ WebRequest request = getPostGitCloneRequest(null, workspacePath, filePath, name, null, null);
+ WebResponse response = webConversation.getResponse(request);
+ assertEquals(HttpURLConnection.HTTP_CREATED, response.getResponseCode());
+ String cloneLocation = response.getHeaderField(ProtocolConstants.HEADER_LOCATION);
+ assertNotNull(cloneLocation);
+
+ // validate the clone metadata
+ response = webConversation.getResponse(getGetRequest(cloneLocation));
+ assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
+ JSONObject clones = new JSONObject(response.getText());
+ 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(filePath.segmentCount() == 2 && n.equals(WebProject.fromId(filePath.segment(1)).getName()) || 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.toURL());
return clone(uri, workspacePath, filePath, name, null, null);