blob: 04baacda369b32106375d8eff1f227dfefdbdec4 [file] [log] [blame]
package com.google.gerrit.acceptance.rest.change;
import static com.google.common.truth.Truth.assertThat;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.extensions.api.projects.BranchInput;
import com.google.gerrit.extensions.client.SubmitType;
import com.google.gerrit.reviewdb.client.Project;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.junit.Test;
import java.util.List;
public class SubmitByMergeIfNecessaryIT extends AbstractSubmitByMerge {
@Override
protected SubmitType getSubmitType() {
return SubmitType.MERGE_IF_NECESSARY;
}
@Test
public void submitWithFastForward() throws Exception {
RevCommit oldHead = getRemoteHead();
PushOneCommit.Result change = createChange();
submit(change.getChangeId());
RevCommit head = getRemoteHead();
assertThat(head.getId()).isEqualTo(change.getCommitId());
assertThat(head.getParent(0)).isEqualTo(oldHead);
assertSubmitter(change.getChangeId(), 1);
assertPersonEquals(admin.getIdent(), head.getAuthorIdent());
assertPersonEquals(admin.getIdent(), head.getCommitterIdent());
}
@Test
public void submitMultipleChanges() throws Exception {
RevCommit initialHead = getRemoteHead();
testRepo.reset(initialHead);
PushOneCommit.Result change2 = createChange("Change 2", "b", "b");
testRepo.reset(initialHead);
PushOneCommit.Result change3 = createChange("Change 3", "c", "c");
testRepo.reset(initialHead);
PushOneCommit.Result change4 = createChange("Change 4", "d", "d");
// Change 2 stays untouched.
approve(change2.getChangeId());
// Change 3 is a fast-forward, no need to merge.
submit(change3.getChangeId());
RevCommit tip = getRemoteLog().get(0);
assertThat(tip.getShortMessage()).isEqualTo(
change3.getCommit().getShortMessage());
assertThat(tip.getParent(0).getId()).isEqualTo(
initialHead.getId());
assertPersonEquals(admin.getIdent(), tip.getAuthorIdent());
assertPersonEquals(admin.getIdent(), tip.getCommitterIdent());
// We need to merge change 4.
submit(change4.getChangeId());
tip = getRemoteLog().get(0);
assertThat(tip.getParent(1).getShortMessage()).isEqualTo(
change4.getCommit().getShortMessage());
assertThat(tip.getParent(0).getShortMessage()).isEqualTo(
change3.getCommit().getShortMessage());
assertPersonEquals(admin.getIdent(), tip.getAuthorIdent());
assertPersonEquals(serverIdent.get(), tip.getCommitterIdent());
assertNew(change2.getChangeId());
}
@Test
public void submitChangesAcrossRepos() throws Exception {
Project.NameKey p1 = createProject("project-where-we-submit");
Project.NameKey p2 = createProject("project-impacted-via-topic");
Project.NameKey p3 = createProject("project-impacted-indirectly-via-topic");
RevCommit initialHead2 = getRemoteHead(p2, "master");
RevCommit initialHead3 = getRemoteHead(p3, "master");
TestRepository<?> repo1 = cloneProject(p1);
TestRepository<?> repo2 = cloneProject(p2);
TestRepository<?> repo3 = cloneProject(p3);
PushOneCommit.Result change1a = createChange(repo1, "master",
"An ancestor of the change we want to submit",
"a.txt", "1", "dependent-topic");
PushOneCommit.Result change1b = createChange(repo1, "master",
"We're interested in submitting this change",
"a.txt", "2", "topic-to-submit");
PushOneCommit.Result change2a = createChange(repo2, "master",
"indirection level 1",
"a.txt", "1", "topic-indirect");
PushOneCommit.Result change2b = createChange(repo2, "master",
"should go in with first change",
"a.txt", "2", "dependent-topic");
PushOneCommit.Result change3 = createChange(repo3, "master",
"indirection level 2",
"a.txt", "1", "topic-indirect");
approve(change1a.getChangeId());
approve(change2a.getChangeId());
approve(change2b.getChangeId());
approve(change3.getChangeId());
submit(change1b.getChangeId());
RevCommit tip1 = getRemoteLog(p1, "master").get(0);
RevCommit tip2 = getRemoteLog(p2, "master").get(0);
RevCommit tip3 = getRemoteLog(p3, "master").get(0);
assertThat(tip1.getShortMessage()).isEqualTo(
change1b.getCommit().getShortMessage());
if (isSubmitWholeTopicEnabled()) {
assertThat(tip2.getShortMessage()).isEqualTo(
change2b.getCommit().getShortMessage());
assertThat(tip3.getShortMessage()).isEqualTo(
change3.getCommit().getShortMessage());
} else {
assertThat(tip2.getShortMessage()).isEqualTo(
initialHead2.getShortMessage());
assertThat(tip3.getShortMessage()).isEqualTo(
initialHead3.getShortMessage());
}
}
@Test
public void submitChangesAcrossReposBlocked() throws Exception {
Project.NameKey p1 = createProject("project-where-we-submit");
Project.NameKey p2 = createProject("project-impacted-via-topic");
Project.NameKey p3 = createProject("project-impacted-indirectly-via-topic");
TestRepository<?> repo1 = cloneProject(p1);
TestRepository<?> repo2 = cloneProject(p2);
TestRepository<?> repo3 = cloneProject(p3);
RevCommit initialHead1 = getRemoteHead(p1, "master");
RevCommit initialHead2 = getRemoteHead(p2, "master");
RevCommit initialHead3 = getRemoteHead(p3, "master");
PushOneCommit.Result change1a = createChange(repo1, "master",
"An ancestor of the change we want to submit",
"a.txt", "1", "dependent-topic");
PushOneCommit.Result change1b = createChange(repo1, "master",
"we're interested to submit this change",
"a.txt", "2", "topic-to-submit");
PushOneCommit.Result change2a = createChange(repo2, "master",
"indirection level 2a",
"a.txt", "1", "topic-indirect");
PushOneCommit.Result change2b = createChange(repo2, "master",
"should go in with first change",
"a.txt", "2", "dependent-topic");
PushOneCommit.Result change3 = createChange(repo3, "master",
"indirection level 2b",
"a.txt", "1", "topic-indirect");
// Create a merge conflict for change3 which is only indirectly related
// via topics.
repo3.reset(initialHead3);
PushOneCommit.Result change3Conflict = createChange(repo3, "master",
"conflicting change",
"a.txt", "2\n2", "conflicting-topic");
submit(change3Conflict.getChangeId());
RevCommit tipConflict = getRemoteLog(p3, "master").get(0);
assertThat(tipConflict.getShortMessage()).isEqualTo(
change3Conflict.getCommit().getShortMessage());
approve(change1a.getChangeId());
approve(change2a.getChangeId());
approve(change2b.getChangeId());
approve(change3.getChangeId());
if (isSubmitWholeTopicEnabled()) {
submitWithConflict(change1b.getChangeId(),
"Cannot merge " + change3.getCommit().name() + "\n" +
"Change could not be merged due to a path conflict.\n\n" +
"Please rebase the change locally " +
"and upload the rebased commit for review.");
} else {
submit(change1b.getChangeId());
}
RevCommit tip1 = getRemoteLog(p1, "master").get(0);
RevCommit tip2 = getRemoteLog(p2, "master").get(0);
RevCommit tip3 = getRemoteLog(p3, "master").get(0);
if (isSubmitWholeTopicEnabled()) {
assertThat(tip1.getShortMessage()).isEqualTo(
initialHead1.getShortMessage());
assertThat(tip2.getShortMessage()).isEqualTo(
initialHead2.getShortMessage());
assertThat(tip3.getShortMessage()).isEqualTo(
change3Conflict.getCommit().getShortMessage());
assertNoSubmitter(change1a.getChangeId(), 1);
assertNoSubmitter(change2a.getChangeId(), 1);
assertNoSubmitter(change2b.getChangeId(), 1);
assertNoSubmitter(change3.getChangeId(), 1);
} else {
assertThat(tip1.getShortMessage()).isEqualTo(
change1b.getCommit().getShortMessage());
assertThat(tip2.getShortMessage()).isEqualTo(
initialHead2.getShortMessage());
assertThat(tip3.getShortMessage()).isEqualTo(
change3Conflict.getCommit().getShortMessage());
assertNoSubmitter(change2a.getChangeId(), 1);
assertNoSubmitter(change2b.getChangeId(), 1);
assertNoSubmitter(change3.getChangeId(), 1);
}
}
@Test
public void submitWithMergedAncestorsOnOtherBranch() throws Exception {
PushOneCommit.Result change1 = createChange(testRepo, "master",
"base commit",
"a.txt", "1", "");
submit(change1.getChangeId());
gApi.projects()
.name(project.get())
.branch("branch")
.create(new BranchInput());
PushOneCommit.Result change2 = createChange(testRepo, "master",
"We want to commit this to master first",
"a.txt", "2", "");
submit(change2.getChangeId());
RevCommit tip1 = getRemoteLog(project, "master").get(0);
assertThat(tip1.getShortMessage()).isEqualTo(
change2.getCommit().getShortMessage());
RevCommit tip2 = getRemoteLog(project, "branch").get(0);
assertThat(tip2.getShortMessage()).isEqualTo(
change1.getCommit().getShortMessage());
PushOneCommit.Result change3 = createChange(testRepo, "branch",
"This commit is based on master, which includes change2, "
+ "but is targeted at branch, which doesn't include it.",
"a.txt", "3", "");
submit(change3.getChangeId());
List<RevCommit> log3 = getRemoteLog(project, "branch");
assertThat(log3.get(0).getShortMessage()).isEqualTo(
change3.getCommit().getShortMessage());
assertThat(log3.get(1).getShortMessage()).isEqualTo(
change2.getCommit().getShortMessage());
}
@Test
public void submitWithOpenAncestorsOnOtherBranch() throws Exception {
PushOneCommit.Result change1 = createChange(testRepo, "master",
"base commit",
"a.txt", "1", "");
submit(change1.getChangeId());
gApi.projects()
.name(project.get())
.branch("branch")
.create(new BranchInput());
PushOneCommit.Result change2 = createChange(testRepo, "master",
"We want to commit this to master first",
"a.txt", "2", "");
approve(change2.getChangeId());
RevCommit tip1 = getRemoteLog(project, "master").get(0);
assertThat(tip1.getShortMessage()).isEqualTo(
change1.getCommit().getShortMessage());
RevCommit tip2 = getRemoteLog(project, "branch").get(0);
assertThat(tip2.getShortMessage()).isEqualTo(
change1.getCommit().getShortMessage());
PushOneCommit.Result change3a = createChange(testRepo, "branch",
"This commit is based on change2 pending for master, "
+ "but is targeted itself at branch, which doesn't include it.",
"a.txt", "3", "a-topic-here");
Project.NameKey p3 = createProject("project-related-to-change3");
TestRepository<?> repo3 = cloneProject(p3);
RevCommit initialHead = getRemoteHead(p3, "master");
PushOneCommit.Result change3b = createChange(repo3, "master",
"some accompanying changes for change3a in another repo "
+ "tied together via topic",
"a.txt", "1", "a-topic-here");
approve(change3b.getChangeId());
submitWithConflict(change3a.getChangeId(), "Cannot merge " +
change3a.getCommit().name() +
"\nMissing dependency");
RevCommit tipbranch = getRemoteLog(project, "branch").get(0);
assertThat(tipbranch.getShortMessage()).isEqualTo(
change1.getCommit().getShortMessage());
RevCommit tipmaster = getRemoteLog(p3, "master").get(0);
assertThat(tipmaster.getShortMessage()).isEqualTo(
initialHead.getShortMessage());
}
}