Add acceptance tests to test submit with different submit types
Verify that submitting with different submit types works as expected
and that the repository is updated correctly.
Change-Id: I2b2c752ea12aeb91400fd2172704ca291b80aa97
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/GitUtil.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/GitUtil.java
index 5f8faff..c17598f 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/GitUtil.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/GitUtil.java
@@ -25,6 +25,7 @@
import com.jcraft.jsch.Session;
import org.eclipse.jgit.api.AddCommand;
+import org.eclipse.jgit.api.CheckoutCommand;
import org.eclipse.jgit.api.CloneCommand;
import org.eclipse.jgit.api.CommitCommand;
import org.eclipse.jgit.api.Git;
@@ -33,6 +34,7 @@
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.JschConfigSessionFactory;
@@ -130,47 +132,58 @@
addCmd.call();
}
- public static String createCommit(Git git, PersonIdent i, String msg)
+ public static Commit createCommit(Git git, PersonIdent i, String msg)
throws GitAPIException, IOException {
- return createCommit(git, i, msg, true, false);
+ return createCommit(git, i, msg, null);
}
- public static void amendCommit(Git git, PersonIdent i, String msg, String changeId)
+ public static Commit amendCommit(Git git, PersonIdent i, String msg, String changeId)
throws GitAPIException, IOException {
msg = ChangeIdUtil.insertId(msg, ObjectId.fromString(changeId.substring(1)));
- createCommit(git, i, msg, false, true);
+ return createCommit(git, i, msg, changeId);
}
- private static String createCommit(Git git, PersonIdent i, String msg,
- boolean insertChangeId, boolean amend) throws GitAPIException, IOException {
- ObjectId changeId = null;
- if (insertChangeId) {
- changeId = computeChangeId(git, i, msg);
- msg = ChangeIdUtil.insertId(msg, changeId);
- }
+ private static Commit createCommit(Git git, PersonIdent i, String msg,
+ String changeId) throws GitAPIException, IOException {
final CommitCommand commitCmd = git.commit();
- commitCmd.setAmend(amend);
+ commitCmd.setAmend(changeId != null);
commitCmd.setAuthor(i);
commitCmd.setCommitter(i);
- commitCmd.setMessage(msg);
- commitCmd.call();
- return changeId != null ? "I" + changeId.getName() : null;
+ if (changeId == null) {
+ ObjectId id = computeChangeId(git, i, msg);
+ changeId = "I" + id.getName();
+ }
+ msg = ChangeIdUtil.insertId(msg, ObjectId.fromString(changeId.substring(1)));
+ commitCmd.setMessage(msg);
+
+ RevCommit c = commitCmd.call();
+ return new Commit(c, changeId);
}
private static ObjectId computeChangeId(Git git, PersonIdent i, String msg)
throws IOException {
RevWalk rw = new RevWalk(git.getRepository());
try {
- RevCommit parent =
- rw.lookupCommit(git.getRepository().getRef(Constants.HEAD).getObjectId());
- return ChangeIdUtil.computeChangeId(parent.getTree(), parent.getId(), i, i, msg);
+ Ref head = git.getRepository().getRef(Constants.HEAD);
+ if (head.getObjectId() != null) {
+ RevCommit parent = rw.lookupCommit(head.getObjectId());
+ return ChangeIdUtil.computeChangeId(parent.getTree(), parent.getId(), i, i, msg);
+ } else {
+ return ChangeIdUtil.computeChangeId(null, null, i, i, msg);
+ }
} finally {
rw.release();
}
}
+ public static void checkout(Git git, String name) throws GitAPIException {
+ CheckoutCommand checkout = git.checkout();
+ checkout.setName(name);
+ checkout.call();
+ }
+
public static PushResult pushHead(Git git, String ref, boolean pushTags)
throws GitAPIException {
PushCommand pushCmd = git.push();
@@ -181,4 +194,22 @@
Iterable<PushResult> r = pushCmd.call();
return Iterables.getOnlyElement(r);
}
+
+ public static class Commit {
+ private final RevCommit commit;
+ private final String changeId;
+
+ Commit(RevCommit commit, String changeId) {
+ this.commit = commit;
+ this.changeId = changeId;
+ }
+
+ public RevCommit getCommit() {
+ return commit;
+ }
+
+ public String getChangeId() {
+ return changeId;
+ }
+ }
}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/PushOneCommit.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/PushOneCommit.java
index 7450565..1c0fafe 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/PushOneCommit.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/PushOneCommit.java
@@ -27,6 +27,7 @@
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.gerrit.acceptance.TestAccount;
+import com.google.gerrit.acceptance.git.GitUtil.Commit;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
@@ -36,7 +37,9 @@
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.transport.PushResult;
import org.eclipse.jgit.transport.RemoteRefUpdate;
import org.eclipse.jgit.transport.RemoteRefUpdate.Status;
@@ -82,15 +85,17 @@
public Result to(Git git, String ref)
throws GitAPIException, IOException {
add(git, fileName, content);
+ Commit c;
if (changeId != null) {
- amendCommit(git, i, subject, changeId);
+ c = amendCommit(git, i, subject, changeId);
} else {
- changeId = createCommit(git, i, subject);
+ c = createCommit(git, i, subject);
+ changeId = c.getChangeId();
}
if (tagName != null) {
git.tag().setName(tagName).setAnnotated(false).call();
}
- return new Result(db, ref, pushHead(git, ref, tagName != null), changeId, subject);
+ return new Result(db, ref, pushHead(git, ref, tagName != null), c, subject);
}
public void setTag(final String tagName) {
@@ -101,32 +106,40 @@
private final ReviewDb db;
private final String ref;
private final PushResult result;
- private final String changeId;
+ private final Commit commit;
private final String subject;
- private Result(ReviewDb db, String ref, PushResult result, String changeId,
+ private Result(ReviewDb db, String ref, PushResult result, Commit commit,
String subject) {
this.db = db;
this.ref = ref;
this.result = result;
- this.changeId = changeId;
+ this.commit = commit;
this.subject = subject;
}
public PatchSet.Id getPatchSetId() throws OrmException {
return Iterables.getOnlyElement(
- db.changes().byKey(new Change.Key(changeId))).currentPatchSetId();
+ db.changes().byKey(new Change.Key(commit.getChangeId()))).currentPatchSetId();
}
public String getChangeId() {
- return changeId;
+ return commit.getChangeId();
+ }
+
+ public ObjectId getCommitId() {
+ return commit.getCommit().getId();
+ }
+
+ public RevCommit getCommit() {
+ return commit.getCommit();
}
public void assertChange(Change.Status expectedStatus,
String expectedTopic, TestAccount... expectedReviewers)
throws OrmException {
Change c =
- Iterables.getOnlyElement(db.changes().byKey(new Change.Key(changeId)).toList());
+ Iterables.getOnlyElement(db.changes().byKey(new Change.Key(commit.getChangeId())).toList());
assertEquals(subject, c.getSubject());
assertEquals(expectedStatus, c.getStatus());
assertEquals(expectedTopic, Strings.emptyToNull(c.getTopic()));
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
new file mode 100644
index 0000000..5209a0c
--- /dev/null
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
@@ -0,0 +1,256 @@
+// Copyright (C) 2013 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.acceptance.rest.change;
+
+import static com.google.gerrit.acceptance.git.GitUtil.cloneProject;
+import static com.google.gerrit.acceptance.git.GitUtil.initSsh;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+
+import com.google.gerrit.acceptance.AbstractDaemonTest;
+import com.google.gerrit.acceptance.AccountCreator;
+import com.google.gerrit.acceptance.RestResponse;
+import com.google.gerrit.acceptance.RestSession;
+import com.google.gerrit.acceptance.SshSession;
+import com.google.gerrit.acceptance.TestAccount;
+import com.google.gerrit.acceptance.git.GitUtil;
+import com.google.gerrit.acceptance.git.PushOneCommit;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.Project.InheritableBoolean;
+import com.google.gerrit.reviewdb.client.Project.SubmitType;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import com.google.gwtorm.server.SchemaFactory;
+import com.google.inject.Inject;
+
+import com.jcraft.jsch.JSchException;
+
+import org.apache.http.HttpStatus;
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.diff.DiffFormatter;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+public abstract class AbstractSubmit extends AbstractDaemonTest {
+
+ @Inject
+ private AccountCreator accounts;
+
+ @Inject
+ private SchemaFactory<ReviewDb> reviewDbProvider;
+
+ @Inject
+ private GitRepositoryManager repoManager;
+
+ protected RestSession session;
+
+ private TestAccount admin;
+ private Project.NameKey project;
+ private ReviewDb db;
+
+ @Before
+ public void setUp() throws Exception {
+ admin = accounts.admin();
+ session = new RestSession(server, admin);
+ initSsh(admin);
+
+ project = new Project.NameKey("p");
+
+ db = reviewDbProvider.open();
+ }
+
+ @After
+ public void cleanup() {
+ db.close();
+ }
+
+ protected abstract SubmitType getSubmitType();
+
+ @Test
+ public void submitToEmptyRepo() throws JSchException, IOException,
+ GitAPIException {
+ Git git = createProject(false);
+ PushOneCommit.Result change = createChange(git);
+ submit(change.getChangeId());
+ assertEquals(change.getCommitId(), getRemoteHead().getId());
+ }
+
+ protected Git createProject() throws JSchException, IOException,
+ GitAPIException {
+ return createProject(true);
+ }
+
+ private Git createProject(boolean emptyCommit)
+ throws JSchException, IOException, GitAPIException {
+ SshSession sshSession = new SshSession(server, admin);
+ try {
+ GitUtil.createProject(sshSession, project.get(), null, emptyCommit);
+ setSubmitType(getSubmitType());
+ return cloneProject(sshSession.getUrl() + "/" + project.get());
+ } finally {
+ sshSession.close();
+ }
+ }
+
+ private void setSubmitType(SubmitType submitType) throws IOException {
+ ProjectConfigInput in = new ProjectConfigInput();
+ in.submit_type = submitType;
+ in.use_content_merge = InheritableBoolean.FALSE;
+ RestResponse r = session.put("/projects/" + project.get() + "/config", in);
+ assertEquals(HttpStatus.SC_OK, r.getStatusCode());
+ r.consume();
+ }
+
+ protected void setUseContentMerge() throws IOException {
+ ProjectConfigInput in = new ProjectConfigInput();
+ in.use_content_merge = InheritableBoolean.TRUE;
+ RestResponse r = session.put("/projects/" + project.get() + "/config", in);
+ assertEquals(HttpStatus.SC_OK, r.getStatusCode());
+ r.consume();
+ }
+
+ protected PushOneCommit.Result createChange(Git git) throws GitAPIException,
+ IOException {
+ PushOneCommit push = new PushOneCommit(db, admin.getIdent());
+ return push.to(git, "refs/for/master");
+ }
+
+ protected PushOneCommit.Result createChange(Git git, String subject,
+ String fileName, String content) throws GitAPIException, IOException {
+ PushOneCommit push =
+ new PushOneCommit(db, admin.getIdent(), subject, fileName, content);
+ return push.to(git, "refs/for/master");
+ }
+
+ protected void submit(String changeId) throws IOException {
+ submit(changeId, HttpStatus.SC_OK);
+ }
+
+ protected void submitWithConflict(String changeId) throws IOException {
+ submit(changeId, HttpStatus.SC_CONFLICT);
+ }
+
+ private void submit(String changeId, int expectedStatus) throws IOException {
+ approve(changeId);
+ RestResponse r =
+ session.post("/changes/" + changeId + "/submit",
+ SubmitInput.waitForMerge());
+ assertEquals(expectedStatus, r.getStatusCode());
+ if (expectedStatus == HttpStatus.SC_OK) {
+ ChangeInfo change =
+ (new Gson()).fromJson(r.getReader(),
+ new TypeToken<ChangeInfo>() {}.getType());
+ assertEquals("MERGED", change.status);
+ }
+ r.consume();
+ }
+
+ private void approve(String changeId) throws IOException {
+ RestResponse r =
+ session.post("/changes/" + changeId + "/revisions/current/review",
+ ReviewInput.approve());
+ assertEquals(HttpStatus.SC_OK, r.getStatusCode());
+ r.consume();
+ }
+
+ protected void assertCherryPick(Git localGit, boolean contentMerge) throws IOException {
+ assertRebase(localGit, contentMerge);
+ RevCommit remoteHead = getRemoteHead();
+ assertFalse(remoteHead.getFooterLines("Reviewed-On").isEmpty());
+ assertFalse(remoteHead.getFooterLines("Reviewed-By").isEmpty());
+ }
+
+ protected void assertRebase(Git localGit, boolean contentMerge) throws IOException {
+ Repository repo = localGit.getRepository();
+ RevCommit localHead = getHead(repo);
+ RevCommit remoteHead = getRemoteHead();
+ assertNotEquals(localHead.getId(), remoteHead.getId());
+ assertEquals(1, remoteHead.getParentCount());
+ if (!contentMerge) {
+ assertEquals(getLatestDiff(repo), getLatestRemoteDiff());
+ }
+ assertEquals(localHead.getShortMessage(), remoteHead.getShortMessage());
+ }
+
+ private RevCommit getHead(Repository repo) throws IOException {
+ return getHead(repo, "HEAD");
+ }
+
+ protected RevCommit getRemoteHead() throws IOException {
+ Repository repo = repoManager.openRepository(project);
+ try {
+ return getHead(repo, "refs/heads/master");
+ } finally {
+ repo.close();
+ }
+ }
+
+ private RevCommit getHead(Repository repo, String name) throws IOException {
+ try {
+ RevWalk rw = new RevWalk(repo);
+ try {
+ return rw.parseCommit(repo.getRef(name).getObjectId());
+ } finally {
+ rw.release();
+ }
+ } finally {
+ repo.close();
+ }
+ }
+
+ private String getLatestDiff(Repository repo) throws IOException {
+ ObjectId oldTreeId = repo.resolve("HEAD~1^{tree}");
+ ObjectId newTreeId = repo.resolve("HEAD^{tree}");
+ return getLatestDiff(repo, oldTreeId, newTreeId);
+ }
+
+ private String getLatestRemoteDiff() throws IOException {
+ Repository repo = repoManager.openRepository(project);
+ try {
+ RevWalk rw = new RevWalk(repo);
+ try {
+ ObjectId oldTreeId = repo.resolve("refs/heads/master~1^{tree}");
+ ObjectId newTreeId = repo.resolve("refs/heads/master^{tree}");
+ return getLatestDiff(repo, oldTreeId, newTreeId);
+ } finally {
+ rw.release();
+ }
+ } finally {
+ repo.close();
+ }
+ }
+
+ private String getLatestDiff(Repository repo, ObjectId oldTreeId,
+ ObjectId newTreeId) throws IOException {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ DiffFormatter fmt = new DiffFormatter(out);
+ fmt.setRepository(repo);
+ fmt.format(oldTreeId, newTreeId);
+ fmt.flush();
+ return out.toString();
+ }
+}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/AbstractSubmitByMerge.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/AbstractSubmitByMerge.java
new file mode 100644
index 0000000..770e554
--- /dev/null
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/AbstractSubmitByMerge.java
@@ -0,0 +1,93 @@
+// Copyright (C) 2013 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.acceptance.rest.change;
+
+import static com.google.gerrit.acceptance.git.GitUtil.checkout;
+import static org.junit.Assert.assertEquals;
+
+import com.google.gerrit.acceptance.git.PushOneCommit;
+
+import com.jcraft.jsch.JSchException;
+
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.junit.Test;
+
+import java.io.IOException;
+
+public abstract class AbstractSubmitByMerge extends AbstractSubmit {
+
+ @Test
+ public void submitWithMerge() throws JSchException, IOException,
+ GitAPIException {
+ Git git = createProject();
+ RevCommit initialHead = getRemoteHead();
+ PushOneCommit.Result change =
+ createChange(git, "Change 1", "a.txt", "content");
+ submit(change.getChangeId());
+
+ RevCommit oldHead = getRemoteHead();
+ checkout(git, initialHead.getId().getName());
+ PushOneCommit.Result change2 =
+ createChange(git, "Change 2", "b.txt", "other content");
+ submit(change2.getChangeId());
+ RevCommit head = getRemoteHead();
+ assertEquals(2, head.getParentCount());
+ assertEquals(oldHead, head.getParent(0));
+ assertEquals(change2.getCommitId(), head.getParent(1));
+ }
+
+ @Test
+ public void submitWithContentMerge() throws JSchException, IOException,
+ GitAPIException {
+ Git git = createProject();
+ setUseContentMerge();
+ PushOneCommit.Result change =
+ createChange(git, "Change 1", "a.txt", "aaa\nbbb\nccc\n");
+ submit(change.getChangeId());
+ PushOneCommit.Result change2 =
+ createChange(git, "Change 2", "a.txt", "aaa\nbbb\nccc\nddd\n");
+ submit(change2.getChangeId());
+
+ RevCommit oldHead = getRemoteHead();
+ checkout(git, change.getCommitId().getName());
+ PushOneCommit.Result change3 =
+ createChange(git, "Change 3", "a.txt", "bbb\nccc\n");
+ submit(change3.getChangeId());
+ RevCommit head = getRemoteHead();
+ assertEquals(2, head.getParentCount());
+ assertEquals(oldHead, head.getParent(0));
+ assertEquals(change3.getCommitId(), head.getParent(1));
+ }
+
+ @Test
+ public void submitWithContentMerge_Conflict() throws JSchException,
+ IOException, GitAPIException {
+ Git git = createProject();
+ setUseContentMerge();
+ RevCommit initialHead = getRemoteHead();
+ PushOneCommit.Result change =
+ createChange(git, "Change 1", "a.txt", "content");
+ submit(change.getChangeId());
+
+ RevCommit oldHead = getRemoteHead();
+ checkout(git, initialHead.getId().getName());
+ PushOneCommit.Result change2 =
+ createChange(git, "Change 2", "a.txt", "other content");
+ submitWithConflict(change2.getChangeId());
+ assertEquals(oldHead, getRemoteHead());
+ }
+}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/BUCK b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/BUCK
index dff94ce..3ae3700 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/BUCK
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/BUCK
@@ -1,14 +1,39 @@
include_defs('//gerrit-acceptance-tests/tests.defs')
acceptance_tests(
- srcs = glob(['*IT.java']),
+ srcs = ['ChangeMessagesIT.java'],
deps = [
':util',
'//gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git:util',
],
)
+acceptance_tests(
+ srcs = ['SubmitByCherryPickIT.java', 'SubmitByFastForwardIT.java',
+ 'SubmitByMergeAlwaysIT.java', 'SubmitByMergeIfNecessaryIT.java',
+ 'SubmitByRebaseIfNecessaryIT.java'],
+ deps = [
+ ':submit',
+ '//gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git:util',
+ ],
+)
+
+java_library(
+ name = 'submit',
+ srcs = ['AbstractSubmit.java', 'AbstractSubmitByMerge.java'],
+ deps = [
+ ':util',
+ '//gerrit-acceptance-tests:lib',
+ '//gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git:util',
+ ],
+)
+
java_library(
name = 'util',
- srcs = ['ChangeInfo.java', 'ChangeMessageInfo.java'],
+ srcs = ['ChangeInfo.java', 'ChangeMessageInfo.java', 'ProjectConfigInput.java',
+ 'ReviewInput.java', 'SubmitInput.java'],
+ deps = [
+ '//lib:guava',
+ '//gerrit-reviewdb:server',
+ ],
)
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ChangeInfo.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ChangeInfo.java
index 4c9325e..3921028 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ChangeInfo.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ChangeInfo.java
@@ -18,4 +18,5 @@
public class ChangeInfo {
List<ChangeMessageInfo> messages;
+ String status;
}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ProjectConfigInput.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ProjectConfigInput.java
new file mode 100644
index 0000000..4d2e4b6
--- /dev/null
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ProjectConfigInput.java
@@ -0,0 +1,23 @@
+// Copyright (C) 2013 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.acceptance.rest.change;
+
+import com.google.gerrit.reviewdb.client.Project.InheritableBoolean;
+import com.google.gerrit.reviewdb.client.Project.SubmitType;
+
+public class ProjectConfigInput {
+ public SubmitType submit_type;
+ public InheritableBoolean use_content_merge;
+}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ReviewInput.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ReviewInput.java
new file mode 100644
index 0000000..a5371d2
--- /dev/null
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ReviewInput.java
@@ -0,0 +1,30 @@
+// Copyright (C) 2013 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.acceptance.rest.change;
+
+import com.google.common.collect.Maps;
+
+import java.util.Map;
+
+public class ReviewInput {
+ Map<String, Integer> labels;
+
+ public static ReviewInput approve() {
+ ReviewInput in = new ReviewInput();
+ in.labels = Maps.newHashMap();
+ in.labels.put("Code-Review", 2);
+ return in;
+ }
+}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByCherryPickIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByCherryPickIT.java
new file mode 100644
index 0000000..ccbbfb6
--- /dev/null
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByCherryPickIT.java
@@ -0,0 +1,143 @@
+// Copyright (C) 2013 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.acceptance.rest.change;
+
+import static com.google.gerrit.acceptance.git.GitUtil.checkout;
+import static org.junit.Assert.assertEquals;
+
+import com.google.gerrit.acceptance.git.PushOneCommit;
+import com.google.gerrit.reviewdb.client.Project.SubmitType;
+
+import com.jcraft.jsch.JSchException;
+
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.junit.Test;
+
+import java.io.IOException;
+
+public class SubmitByCherryPickIT extends AbstractSubmit {
+
+ @Override
+ protected SubmitType getSubmitType() {
+ return SubmitType.CHERRY_PICK;
+ }
+
+ @Test
+ public void submitWithCherryPickIfFastForwardPossible() throws JSchException,
+ IOException, GitAPIException {
+ Git git = createProject();
+ PushOneCommit.Result change = createChange(git);
+ submit(change.getChangeId());
+ assertCherryPick(git, false);
+ assertEquals(change.getCommit().getParent(0),
+ getRemoteHead().getParent(0));
+ }
+
+ @Test
+ public void submitWithCherryPick() throws JSchException, IOException,
+ GitAPIException {
+ Git git = createProject();
+ RevCommit initialHead = getRemoteHead();
+ PushOneCommit.Result change =
+ createChange(git, "Change 1", "a.txt", "content");
+ submit(change.getChangeId());
+
+ RevCommit oldHead = getRemoteHead();
+ checkout(git, initialHead.getId().getName());
+ PushOneCommit.Result change2 =
+ createChange(git, "Change 2", "b.txt", "other content");
+ submit(change2.getChangeId());
+ assertCherryPick(git, false);
+ assertEquals(oldHead, getRemoteHead().getParent(0));
+ }
+
+ @Test
+ public void submitWithContentMerge() throws JSchException, IOException,
+ GitAPIException {
+ Git git = createProject();
+ setUseContentMerge();
+ PushOneCommit.Result change =
+ createChange(git, "Change 1", "a.txt", "aaa\nbbb\nccc\n");
+ submit(change.getChangeId());
+ PushOneCommit.Result change2 =
+ createChange(git, "Change 2", "a.txt", "aaa\nbbb\nccc\nddd\n");
+ submit(change2.getChangeId());
+
+ RevCommit oldHead = getRemoteHead();
+ checkout(git, change.getCommitId().getName());
+ PushOneCommit.Result change3 =
+ createChange(git, "Change 3", "a.txt", "bbb\nccc\n");
+ submit(change3.getChangeId());
+ assertCherryPick(git, true);
+ assertEquals(oldHead, getRemoteHead().getParent(0));
+ }
+
+ @Test
+ public void submitWithContentMerge_Conflict() throws JSchException,
+ IOException, GitAPIException {
+ Git git = createProject();
+ setUseContentMerge();
+ RevCommit initialHead = getRemoteHead();
+ PushOneCommit.Result change =
+ createChange(git, "Change 1", "a.txt", "content");
+ submit(change.getChangeId());
+
+ RevCommit oldHead = getRemoteHead();
+ checkout(git, initialHead.getId().getName());
+ PushOneCommit.Result change2 =
+ createChange(git, "Change 2", "a.txt", "other content");
+ submitWithConflict(change2.getChangeId());
+ assertEquals(oldHead, getRemoteHead());
+ }
+
+ @Test
+ public void submitOutOfOrder() throws JSchException, IOException,
+ GitAPIException {
+ Git git = createProject();
+ RevCommit initialHead = getRemoteHead();
+ PushOneCommit.Result change =
+ createChange(git, "Change 1", "a.txt", "content");
+ submit(change.getChangeId());
+
+ RevCommit oldHead = getRemoteHead();
+ checkout(git, initialHead.getId().getName());
+ createChange(git, "Change 2", "b.txt", "other content");
+ PushOneCommit.Result change3 =
+ createChange(git, "Change 3", "c.txt", "different content");
+ submit(change3.getChangeId());
+ assertCherryPick(git, false);
+ assertEquals(oldHead, getRemoteHead().getParent(0));
+ }
+
+ @Test
+ public void submitOutOfOrder_Conflict() throws JSchException, IOException,
+ GitAPIException {
+ Git git = createProject();
+ RevCommit initialHead = getRemoteHead();
+ PushOneCommit.Result change =
+ createChange(git, "Change 1", "a.txt", "content");
+ submit(change.getChangeId());
+
+ RevCommit oldHead = getRemoteHead();
+ checkout(git, initialHead.getId().getName());
+ createChange(git, "Change 2", "b.txt", "other content");
+ PushOneCommit.Result change3 =
+ createChange(git, "Change 3", "b.txt", "different content");
+ submitWithConflict(change3.getChangeId());
+ assertEquals(oldHead, getRemoteHead());
+ }
+}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByFastForwardIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByFastForwardIT.java
new file mode 100644
index 0000000..9d56e18
--- /dev/null
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByFastForwardIT.java
@@ -0,0 +1,67 @@
+// Copyright (C) 2013 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.acceptance.rest.change;
+
+import static com.google.gerrit.acceptance.git.GitUtil.checkout;
+import static org.junit.Assert.assertEquals;
+
+import com.google.gerrit.acceptance.git.PushOneCommit;
+import com.google.gerrit.reviewdb.client.Project.SubmitType;
+
+import com.jcraft.jsch.JSchException;
+
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.junit.Test;
+
+import java.io.IOException;
+
+public class SubmitByFastForwardIT extends AbstractSubmit {
+
+ @Override
+ protected SubmitType getSubmitType() {
+ return SubmitType.FAST_FORWARD_ONLY;
+ }
+
+ @Test
+ public void submitWithFastForward() throws JSchException, IOException,
+ GitAPIException {
+ Git git = createProject();
+ RevCommit oldHead = getRemoteHead();
+ PushOneCommit.Result change = createChange(git);
+ submit(change.getChangeId());
+ RevCommit head = getRemoteHead();
+ assertEquals(change.getCommitId(), head.getId());
+ assertEquals(oldHead, head.getParent(0));
+ }
+
+ @Test
+ public void submitFastForwardNotPossible_Conflict() throws JSchException, IOException,
+ GitAPIException {
+ Git git = createProject();
+ RevCommit initialHead = getRemoteHead();
+ PushOneCommit.Result change =
+ createChange(git, "Change 1", "a.txt", "content");
+ submit(change.getChangeId());
+
+ RevCommit oldHead = getRemoteHead();
+ checkout(git, initialHead.getId().getName());
+ PushOneCommit.Result change2 =
+ createChange(git, "Change 2", "b.txt", "other content");
+ submitWithConflict(change2.getChangeId());
+ assertEquals(oldHead, getRemoteHead());
+ }
+}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByMergeAlwaysIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByMergeAlwaysIT.java
new file mode 100644
index 0000000..6c671eb
--- /dev/null
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByMergeAlwaysIT.java
@@ -0,0 +1,50 @@
+// Copyright (C) 2013 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.acceptance.rest.change;
+
+import static org.junit.Assert.assertEquals;
+
+import com.google.gerrit.acceptance.git.PushOneCommit;
+import com.google.gerrit.reviewdb.client.Project.SubmitType;
+
+import com.jcraft.jsch.JSchException;
+
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.junit.Test;
+
+import java.io.IOException;
+
+public class SubmitByMergeAlwaysIT extends AbstractSubmitByMerge {
+
+ @Override
+ protected SubmitType getSubmitType() {
+ return SubmitType.MERGE_ALWAYS;
+ }
+
+ @Test
+ public void submitWithMergeIfFastForwardPossible() throws JSchException,
+ IOException, GitAPIException {
+ Git git = createProject();
+ RevCommit oldHead = getRemoteHead();
+ PushOneCommit.Result change = createChange(git);
+ submit(change.getChangeId());
+ RevCommit head = getRemoteHead();
+ assertEquals(2, head.getParentCount());
+ assertEquals(oldHead, head.getParent(0));
+ assertEquals(change.getCommitId(), head.getParent(1));
+ }
+}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByMergeIfNecessaryIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByMergeIfNecessaryIT.java
new file mode 100644
index 0000000..a5737a7
--- /dev/null
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByMergeIfNecessaryIT.java
@@ -0,0 +1,35 @@
+package com.google.gerrit.acceptance.rest.change;
+
+import static org.junit.Assert.assertEquals;
+
+import com.google.gerrit.acceptance.git.PushOneCommit;
+import com.google.gerrit.reviewdb.client.Project.SubmitType;
+
+import com.jcraft.jsch.JSchException;
+
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.junit.Test;
+
+import java.io.IOException;
+
+public class SubmitByMergeIfNecessaryIT extends AbstractSubmitByMerge {
+
+ @Override
+ protected SubmitType getSubmitType() {
+ return SubmitType.MERGE_IF_NECESSARY;
+ }
+
+ @Test
+ public void submitWithFastForward() throws JSchException, IOException,
+ GitAPIException {
+ Git git = createProject();
+ RevCommit oldHead = getRemoteHead();
+ PushOneCommit.Result change = createChange(git);
+ submit(change.getChangeId());
+ RevCommit head = getRemoteHead();
+ assertEquals(change.getCommitId(), head.getId());
+ assertEquals(oldHead, head.getParent(0));
+ }
+}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByRebaseIfNecessaryIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByRebaseIfNecessaryIT.java
new file mode 100644
index 0000000..07594a6
--- /dev/null
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByRebaseIfNecessaryIT.java
@@ -0,0 +1,108 @@
+// Copyright (C) 2013 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.acceptance.rest.change;
+
+import static com.google.gerrit.acceptance.git.GitUtil.checkout;
+import static org.junit.Assert.assertEquals;
+
+import com.google.gerrit.acceptance.git.PushOneCommit;
+import com.google.gerrit.reviewdb.client.Project.SubmitType;
+
+import com.jcraft.jsch.JSchException;
+
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.junit.Test;
+
+import java.io.IOException;
+
+public class SubmitByRebaseIfNecessaryIT extends AbstractSubmit {
+
+ @Override
+ protected SubmitType getSubmitType() {
+ return SubmitType.REBASE_IF_NECESSARY;
+ }
+
+ @Test
+ public void submitWithFastForward() throws JSchException, IOException,
+ GitAPIException {
+ Git git = createProject();
+ RevCommit oldHead = getRemoteHead();
+ PushOneCommit.Result change = createChange(git);
+ submit(change.getChangeId());
+ RevCommit head = getRemoteHead();
+ assertEquals(change.getCommitId(), head.getId());
+ assertEquals(oldHead, head.getParent(0));
+ }
+
+ @Test
+ public void submitWithRebase() throws JSchException, IOException,
+ GitAPIException {
+ Git git = createProject();
+ RevCommit initialHead = getRemoteHead();
+ PushOneCommit.Result change =
+ createChange(git, "Change 1", "a.txt", "content");
+ submit(change.getChangeId());
+
+ RevCommit oldHead = getRemoteHead();
+ checkout(git, initialHead.getId().getName());
+ PushOneCommit.Result change2 =
+ createChange(git, "Change 2", "b.txt", "other content");
+ submit(change2.getChangeId());
+ assertRebase(git, false);
+ assertEquals(oldHead, getRemoteHead().getParent(0));
+ }
+
+ @Test
+ public void submitWithContentMerge() throws JSchException, IOException,
+ GitAPIException {
+ Git git = createProject();
+ setUseContentMerge();
+ PushOneCommit.Result change =
+ createChange(git, "Change 1", "a.txt", "aaa\nbbb\nccc\n");
+ submit(change.getChangeId());
+ PushOneCommit.Result change2 =
+ createChange(git, "Change 2", "a.txt", "aaa\nbbb\nccc\nddd\n");
+ submit(change2.getChangeId());
+
+ RevCommit oldHead = getRemoteHead();
+ checkout(git, change.getCommitId().getName());
+ PushOneCommit.Result change3 =
+ createChange(git, "Change 3", "a.txt", "bbb\nccc\n");
+ submit(change3.getChangeId());
+ assertRebase(git, true);
+ assertEquals(oldHead, getRemoteHead().getParent(0));
+ }
+
+ @Test
+ public void submitWithContentMerge_Conflict() throws JSchException,
+ IOException, GitAPIException {
+ Git git = createProject();
+ setUseContentMerge();
+ RevCommit initialHead = getRemoteHead();
+ PushOneCommit.Result change =
+ createChange(git, "Change 1", "a.txt", "content");
+ submit(change.getChangeId());
+
+ RevCommit oldHead = getRemoteHead();
+ checkout(git, initialHead.getId().getName());
+ PushOneCommit.Result change2 =
+ createChange(git, "Change 2", "a.txt", "other content");
+ submitWithConflict(change2.getChangeId());
+ RevCommit head = getRemoteHead();
+ assertEquals(oldHead, head);
+ }
+}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitInput.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitInput.java
new file mode 100644
index 0000000..8e1b340
--- /dev/null
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitInput.java
@@ -0,0 +1,25 @@
+// Copyright (C) 2013 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.acceptance.rest.change;
+
+public class SubmitInput {
+ boolean wait_for_merge;
+
+ public static SubmitInput waitForMerge() {
+ SubmitInput in = new SubmitInput();
+ in.wait_for_merge = true;
+ return in;
+ }
+}