SubmitByMergeIfNecessary: Test indirectly related changes

When we submit a change all its ancestors are also submitted. We need
to make sure that the ancestors also follow the submitWholeTopic rule.
That is if they have a topic all the changes with their topic needs to
be integrated as well.

This first two tests chain changes over 3 topics and the change in the
first and last topic are not related to each other except for having a
dependency over the second topic. Make sure all of these changes are
merged or none are merged.

The last two changes are testing the ancestor submission. The ancestors
may have changes which are targeted at the same branch or another branch.
We only collect the changes on the same branch. Even if there are open
and reviewd changes on other branches, we should ignore them
when submitting ancestors.

Change-Id: I7c6e5e864a3a0317104724621a29f6608646ad93
This commit is contained in:
Stefan Beller
2015-06-19 17:18:26 -07:00
parent c5993446eb
commit 7c13ccf2c7
2 changed files with 243 additions and 4 deletions

View File

@@ -186,6 +186,14 @@ public abstract class AbstractSubmit extends AbstractDaemonTest {
return push.to("refs/for/master/" + topic);
}
protected PushOneCommit.Result createChange(TestRepository<?> repo,
String branch, String subject, String fileName, String content,
String topic) throws Exception {
PushOneCommit push =
pushFactory.create(db, admin.getIdent(), repo, subject, fileName, content);
return push.to("refs/for/" + branch + "/" + name(topic));
}
protected void submit(String changeId) throws Exception {
submit(changeId, HttpStatus.SC_OK);
}
@@ -303,12 +311,19 @@ public abstract class AbstractSubmit extends AbstractDaemonTest {
return getHead(repo, "HEAD");
}
protected RevCommit getRemoteHead() throws IOException {
protected RevCommit getRemoteHead(Project.NameKey project, String branch)
throws IOException {
try (Repository repo = repoManager.openRepository(project)) {
return getHead(repo, "refs/heads/master");
return getHead(repo, "refs/heads/" + branch);
}
}
protected RevCommit getRemoteHead()
throws IOException {
return getRemoteHead(project, "master");
}
protected List<RevCommit> getRemoteLog(Project.NameKey project, String branch)
throws IOException {
try (Repository repo = repoManager.openRepository(project);

View File

@@ -3,8 +3,11 @@ 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;
@@ -45,8 +48,7 @@ public class SubmitByMergeIfNecessaryIT extends AbstractSubmitByMerge {
submitStatusOnly(change3.getChangeId());
submit(change4.getChangeId());
List<RevCommit> log = getRemoteLog();
RevCommit tip = log.get(0);
RevCommit tip = getRemoteLog().get(0);
assertThat(tip.getParent(1).getShortMessage()).isEqualTo(
change4.getCommit().getShortMessage());
@@ -60,4 +62,226 @@ public class SubmitByMergeIfNecessaryIT extends AbstractSubmitByMerge {
assertThat(tip.getParent(0).getId()).isEqualTo(initialHead.getId());
}
@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());
} 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());
} else {
assertThat(tip1.getShortMessage()).isEqualTo(
change1b.getCommit().getShortMessage());
assertThat(tip2.getShortMessage()).isEqualTo(
initialHead2.getShortMessage());
assertThat(tip3.getShortMessage()).isEqualTo(
change3Conflict.getCommit().getShortMessage());
}
}
@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());
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());
}
}