567 lines
22 KiB
Java
567 lines
22 KiB
Java
// 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.common.truth.Truth.assertThat;
|
|
import static org.junit.Assert.fail;
|
|
|
|
import com.google.gerrit.acceptance.GitUtil;
|
|
import com.google.gerrit.acceptance.PushOneCommit;
|
|
import com.google.gerrit.acceptance.TestProjectInput;
|
|
import com.google.gerrit.extensions.api.changes.ChangeApi;
|
|
import com.google.gerrit.extensions.api.changes.CherryPickInput;
|
|
import com.google.gerrit.extensions.api.changes.ReviewInput;
|
|
import com.google.gerrit.extensions.api.projects.BranchInput;
|
|
import com.google.gerrit.extensions.client.SubmitType;
|
|
import com.google.gerrit.extensions.restapi.BinaryResult;
|
|
import com.google.gerrit.extensions.restapi.RestApiException;
|
|
import com.google.gerrit.reviewdb.client.Branch;
|
|
import com.google.gerrit.reviewdb.client.Project;
|
|
import java.io.File;
|
|
import java.io.FileInputStream;
|
|
import java.io.FileOutputStream;
|
|
import java.io.InputStream;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.zip.GZIPInputStream;
|
|
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
|
|
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
|
|
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
|
|
import org.eclipse.jgit.junit.TestRepository;
|
|
import org.eclipse.jgit.revwalk.RevCommit;
|
|
import org.eclipse.jgit.revwalk.RevTree;
|
|
import org.eclipse.jgit.transport.RefSpec;
|
|
import org.junit.Test;
|
|
|
|
public class SubmitByMergeIfNecessaryIT extends AbstractSubmitByMerge {
|
|
|
|
@Override
|
|
protected SubmitType getSubmitType() {
|
|
return SubmitType.MERGE_IF_NECESSARY;
|
|
}
|
|
|
|
@Test
|
|
public void submitWithFastForward() throws Exception {
|
|
RevCommit initialHead = getRemoteHead();
|
|
PushOneCommit.Result change = createChange();
|
|
submit(change.getChangeId());
|
|
RevCommit updatedHead = getRemoteHead();
|
|
assertThat(updatedHead.getId()).isEqualTo(change.getCommit());
|
|
assertThat(updatedHead.getParent(0)).isEqualTo(initialHead);
|
|
assertSubmitter(change.getChangeId(), 1);
|
|
assertPersonEquals(admin.getIdent(), updatedHead.getAuthorIdent());
|
|
assertPersonEquals(admin.getIdent(), updatedHead.getCommitterIdent());
|
|
|
|
assertRefUpdatedEvents(initialHead, updatedHead);
|
|
assertChangeMergedEvents(change.getChangeId(), updatedHead.name());
|
|
}
|
|
|
|
@Test
|
|
public void submitMultipleChanges() throws Exception {
|
|
RevCommit initialHead = getRemoteHead();
|
|
|
|
testRepo.reset(initialHead);
|
|
PushOneCommit.Result change = createChange("Change 1", "b", "b");
|
|
|
|
testRepo.reset(initialHead);
|
|
PushOneCommit.Result change2 = createChange("Change 2", "c", "c");
|
|
|
|
testRepo.reset(initialHead);
|
|
PushOneCommit.Result change3 = createChange("Change 3", "d", "d");
|
|
PushOneCommit.Result change4 = createChange("Change 4", "e", "e");
|
|
PushOneCommit.Result change5 = createChange("Change 5", "f", "f");
|
|
|
|
// Change 2 is a fast-forward, no need to merge.
|
|
submit(change2.getChangeId());
|
|
|
|
RevCommit headAfterFirstSubmit = getRemoteLog().get(0);
|
|
assertThat(headAfterFirstSubmit.getShortMessage())
|
|
.isEqualTo(change2.getCommit().getShortMessage());
|
|
assertThat(headAfterFirstSubmit.getParent(0).getId()).isEqualTo(initialHead.getId());
|
|
assertPersonEquals(admin.getIdent(), headAfterFirstSubmit.getAuthorIdent());
|
|
assertPersonEquals(admin.getIdent(), headAfterFirstSubmit.getCommitterIdent());
|
|
|
|
// We need to merge changes 3, 4 and 5.
|
|
approve(change3.getChangeId());
|
|
approve(change4.getChangeId());
|
|
submit(change5.getChangeId());
|
|
|
|
RevCommit headAfterSecondSubmit = getRemoteLog().get(0);
|
|
assertThat(headAfterSecondSubmit.getParent(1).getShortMessage())
|
|
.isEqualTo(change5.getCommit().getShortMessage());
|
|
assertThat(headAfterSecondSubmit.getParent(0).getShortMessage())
|
|
.isEqualTo(change2.getCommit().getShortMessage());
|
|
|
|
assertPersonEquals(admin.getIdent(), headAfterSecondSubmit.getAuthorIdent());
|
|
assertPersonEquals(serverIdent.get(), headAfterSecondSubmit.getCommitterIdent());
|
|
|
|
// First change stays untouched.
|
|
assertNew(change.getChangeId());
|
|
|
|
// The two submit operations should have resulted in two ref-update events
|
|
// and three change-merged events.
|
|
assertRefUpdatedEvents(
|
|
initialHead, headAfterFirstSubmit, headAfterFirstSubmit, headAfterSecondSubmit);
|
|
assertChangeMergedEvents(
|
|
change2.getChangeId(),
|
|
headAfterFirstSubmit.name(),
|
|
change3.getChangeId(),
|
|
headAfterSecondSubmit.name(),
|
|
change4.getChangeId(),
|
|
headAfterSecondSubmit.name(),
|
|
change5.getChangeId(),
|
|
headAfterSecondSubmit.name());
|
|
}
|
|
|
|
@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());
|
|
|
|
// get a preview before submitting:
|
|
BinaryResult request = submitPreview(change1b.getChangeId());
|
|
Map<Branch.NameKey, RevTree> preview = fetchFromBundles(request);
|
|
|
|
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());
|
|
|
|
// check that the preview matched what happened:
|
|
assertThat(preview).hasSize(3);
|
|
|
|
assertThat(preview).containsKey(new Branch.NameKey(p1, "refs/heads/master"));
|
|
assertRevTrees(p1, preview);
|
|
|
|
assertThat(preview).containsKey(new Branch.NameKey(p2, "refs/heads/master"));
|
|
assertRevTrees(p2, preview);
|
|
|
|
assertThat(preview).containsKey(new Branch.NameKey(p3, "refs/heads/master"));
|
|
assertRevTrees(p3, preview);
|
|
} else {
|
|
assertThat(tip2.getShortMessage()).isEqualTo(initialHead2.getShortMessage());
|
|
assertThat(tip3.getShortMessage()).isEqualTo(initialHead3.getShortMessage());
|
|
assertThat(preview).hasSize(1);
|
|
assertThat(preview.get(new Branch.NameKey(p1, "refs/heads/master"))).isNotNull();
|
|
}
|
|
}
|
|
|
|
@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()) {
|
|
String msg =
|
|
"Failed to submit 5 changes due to the following problems:\n"
|
|
+ "Change "
|
|
+ change3.getChange().getId()
|
|
+ ": Change could not be "
|
|
+ "merged due to a path conflict. Please rebase the change locally "
|
|
+ "and upload the rebased commit for review.";
|
|
|
|
// Get a preview before submitting:
|
|
try {
|
|
// We cannot just use the ExpectedException infrastructure as provided
|
|
// by AbstractDaemonTest, as then we'd stop early and not test the
|
|
// actual submit.
|
|
submitPreview(change1b.getChangeId());
|
|
fail("expected failure");
|
|
} catch (RestApiException e) {
|
|
assertThat(e.getMessage()).isEqualTo(msg);
|
|
}
|
|
submitWithConflict(change1b.getChangeId(), msg);
|
|
} 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 {
|
|
RevCommit initialHead = getRemoteHead();
|
|
|
|
PushOneCommit.Result change1 =
|
|
createChange(testRepo, "master", "base commit", "a.txt", "1", "");
|
|
submit(change1.getChangeId());
|
|
RevCommit headAfterFirstSubmit = getRemoteHead();
|
|
|
|
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 headAfterSecondSubmit = getRemoteLog(project, "master").get(0);
|
|
assertThat(headAfterSecondSubmit.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());
|
|
|
|
assertRefUpdatedEvents(
|
|
initialHead, headAfterFirstSubmit, headAfterFirstSubmit, headAfterSecondSubmit);
|
|
assertChangeMergedEvents(
|
|
change1.getChangeId(),
|
|
headAfterFirstSubmit.name(),
|
|
change2.getChangeId(),
|
|
headAfterSecondSubmit.name());
|
|
}
|
|
|
|
@Test
|
|
public void submitWithOpenAncestorsOnOtherBranch() throws Exception {
|
|
RevCommit initialHead = getRemoteHead();
|
|
PushOneCommit.Result change1 =
|
|
createChange(testRepo, "master", "base commit", "a.txt", "1", "");
|
|
submit(change1.getChangeId());
|
|
RevCommit headAfterFirstSubmit = getRemoteHead();
|
|
|
|
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 repo3Head = 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());
|
|
|
|
String cnt = isSubmitWholeTopicEnabled() ? "2 changes" : "1 change";
|
|
submitWithConflict(
|
|
change3a.getChangeId(),
|
|
"Failed to submit "
|
|
+ cnt
|
|
+ " due to the following problems:\n"
|
|
+ "Change "
|
|
+ change3a.getChange().getId()
|
|
+ ": depends on change that"
|
|
+ " was not submitted");
|
|
|
|
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(repo3Head.getShortMessage());
|
|
|
|
assertRefUpdatedEvents(initialHead, headAfterFirstSubmit);
|
|
assertChangeMergedEvents(change1.getChangeId(), headAfterFirstSubmit.name());
|
|
}
|
|
|
|
@Test
|
|
public void gerritWorkflow() throws Exception {
|
|
RevCommit initialHead = getRemoteHead();
|
|
|
|
// We'll setup a master and a stable branch.
|
|
// Then we create a change to be applied to master, which is
|
|
// then cherry picked back to stable. The stable branch will
|
|
// be merged up into master again.
|
|
gApi.projects().name(project.get()).branch("stable").create(new BranchInput());
|
|
|
|
// Push a change to master
|
|
PushOneCommit push =
|
|
pushFactory.create(db, user.getIdent(), testRepo, "small fix", "a.txt", "2");
|
|
PushOneCommit.Result change = push.to("refs/for/master");
|
|
submit(change.getChangeId());
|
|
RevCommit headAfterFirstSubmit = getRemoteLog(project, "master").get(0);
|
|
assertThat(headAfterFirstSubmit.getShortMessage())
|
|
.isEqualTo(change.getCommit().getShortMessage());
|
|
|
|
// Now cherry pick to stable
|
|
CherryPickInput in = new CherryPickInput();
|
|
in.destination = "stable";
|
|
in.message = "This goes to stable as well\n" + headAfterFirstSubmit.getFullMessage();
|
|
ChangeApi orig = gApi.changes().id(change.getChangeId());
|
|
String cherryId = orig.current().cherryPick(in).id();
|
|
gApi.changes().id(cherryId).current().review(ReviewInput.approve());
|
|
gApi.changes().id(cherryId).current().submit();
|
|
|
|
// Create the merge locally
|
|
RevCommit stable = getRemoteHead(project, "stable");
|
|
RevCommit master = getRemoteHead(project, "master");
|
|
testRepo.git().fetch().call();
|
|
testRepo.git().branchCreate().setName("stable").setStartPoint(stable).call();
|
|
testRepo.git().branchCreate().setName("master").setStartPoint(master).call();
|
|
|
|
RevCommit merge =
|
|
testRepo
|
|
.commit()
|
|
.parent(master)
|
|
.parent(stable)
|
|
.message("Merge stable into master")
|
|
.insertChangeId()
|
|
.create();
|
|
|
|
testRepo.branch("refs/heads/master").update(merge);
|
|
testRepo.git().push().setRefSpecs(new RefSpec("refs/heads/master:refs/for/master")).call();
|
|
|
|
String changeId = GitUtil.getChangeId(testRepo, merge).get();
|
|
approve(changeId);
|
|
submit(changeId);
|
|
RevCommit headAfterSecondSubmit = getRemoteLog(project, "master").get(0);
|
|
assertThat(headAfterSecondSubmit.getShortMessage()).isEqualTo(merge.getShortMessage());
|
|
|
|
assertRefUpdatedEvents(
|
|
initialHead, headAfterFirstSubmit, headAfterFirstSubmit, headAfterSecondSubmit);
|
|
assertChangeMergedEvents(
|
|
change.getChangeId(), headAfterFirstSubmit.name(), changeId, headAfterSecondSubmit.name());
|
|
}
|
|
|
|
@Test
|
|
public void openChangeForTargetBranchPreventsMerge() throws Exception {
|
|
gApi.projects().name(project.get()).branch("stable").create(new BranchInput());
|
|
|
|
// Propose a change for master, but leave it open for master!
|
|
PushOneCommit change =
|
|
pushFactory.create(db, user.getIdent(), testRepo, "small fix", "a.txt", "2");
|
|
PushOneCommit.Result change2result = change.to("refs/for/master");
|
|
|
|
// Now cherry pick to stable
|
|
CherryPickInput in = new CherryPickInput();
|
|
in.destination = "stable";
|
|
in.message = "it goes to stable branch";
|
|
ChangeApi orig = gApi.changes().id(change2result.getChangeId());
|
|
ChangeApi cherry = orig.current().cherryPick(in);
|
|
cherry.current().review(ReviewInput.approve());
|
|
cherry.current().submit();
|
|
|
|
// Create a commit locally
|
|
testRepo.git().fetch().setRefSpecs(new RefSpec("refs/heads/stable")).call();
|
|
|
|
PushOneCommit.Result change3 = createChange(testRepo, "stable", "test", "a.txt", "3", "");
|
|
submitWithConflict(
|
|
change3.getChangeId(),
|
|
"Failed to submit 1 change due to the following problems:\n"
|
|
+ "Change "
|
|
+ change3.getPatchSetId().getParentKey().get()
|
|
+ ": depends on change that was not submitted");
|
|
|
|
assertRefUpdatedEvents();
|
|
assertChangeMergedEvents();
|
|
}
|
|
|
|
@Test
|
|
@TestProjectInput(createEmptyCommit = false)
|
|
public void mergeWithMissingChange() throws Exception {
|
|
// create a draft change
|
|
PushOneCommit.Result draftResult = createDraftChange();
|
|
|
|
// create a new change based on the draft change
|
|
PushOneCommit.Result changeResult = createChange();
|
|
|
|
// delete the draft change
|
|
gApi.changes().id(draftResult.getChangeId()).delete();
|
|
|
|
// approve and submit the change
|
|
submitWithConflict(
|
|
changeResult.getChangeId(),
|
|
"Failed to submit 1 change due to the following problems:\n"
|
|
+ "Change "
|
|
+ changeResult.getChange().getId()
|
|
+ ": depends on change that was not submitted");
|
|
|
|
assertRefUpdatedEvents();
|
|
assertChangeMergedEvents();
|
|
}
|
|
|
|
@Test
|
|
public void testPreviewSubmitTgz() throws Exception {
|
|
Project.NameKey p1 = createProject("project-name");
|
|
|
|
TestRepository<?> repo1 = cloneProject(p1);
|
|
PushOneCommit.Result change1 = createChange(repo1, "master", "test", "a.txt", "1", "topic");
|
|
approve(change1.getChangeId());
|
|
|
|
// get a preview before submitting:
|
|
BinaryResult request = submitPreview(change1.getChangeId(), "tgz");
|
|
|
|
assertThat(request.getContentType()).isEqualTo("application/x-gzip");
|
|
File tempfile = File.createTempFile("test", null);
|
|
request.writeTo(new FileOutputStream(tempfile));
|
|
|
|
InputStream is = new GZIPInputStream(new FileInputStream(tempfile));
|
|
|
|
List<String> untarredFiles = new ArrayList<>();
|
|
try (TarArchiveInputStream tarInputStream =
|
|
(TarArchiveInputStream) new ArchiveStreamFactory().createArchiveInputStream("tar", is)) {
|
|
TarArchiveEntry entry = null;
|
|
while ((entry = (TarArchiveEntry) tarInputStream.getNextEntry()) != null) {
|
|
untarredFiles.add(entry.getName());
|
|
}
|
|
}
|
|
assertThat(untarredFiles).containsExactly(name("project-name") + ".git");
|
|
}
|
|
}
|