summaryrefslogtreecommitdiffstats
path: root/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/revision/RevisionIT.java
diff options
context:
space:
mode:
Diffstat (limited to 'gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/revision/RevisionIT.java')
-rw-r--r--gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/revision/RevisionIT.java1441
1 files changed, 0 insertions, 1441 deletions
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/revision/RevisionIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/revision/RevisionIT.java
deleted file mode 100644
index 99f4fef2b0..0000000000
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/revision/RevisionIT.java
+++ /dev/null
@@ -1,1441 +0,0 @@
-// 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.api.revision;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth8.assertThat;
-import static com.google.gerrit.acceptance.PushOneCommit.FILE_CONTENT;
-import static com.google.gerrit.acceptance.PushOneCommit.FILE_NAME;
-import static com.google.gerrit.acceptance.PushOneCommit.PATCH;
-import static com.google.gerrit.acceptance.PushOneCommit.PATCH_FILE_ONLY;
-import static com.google.gerrit.acceptance.PushOneCommit.SUBJECT;
-import static com.google.gerrit.extensions.client.ListChangesOption.DETAILED_LABELS;
-import static com.google.gerrit.reviewdb.client.Patch.COMMIT_MSG;
-import static com.google.gerrit.reviewdb.client.Patch.MERGE_LIST;
-import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static java.util.stream.Collectors.toList;
-import static org.eclipse.jgit.lib.Constants.HEAD;
-import static org.junit.Assert.fail;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Iterators;
-import com.google.common.collect.ListMultimap;
-import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.PushOneCommit;
-import com.google.gerrit.acceptance.RestResponse;
-import com.google.gerrit.acceptance.TestAccount;
-import com.google.gerrit.acceptance.TestProjectInput;
-import com.google.gerrit.common.data.Permission;
-import com.google.gerrit.extensions.api.changes.ChangeApi;
-import com.google.gerrit.extensions.api.changes.CherryPickInput;
-import com.google.gerrit.extensions.api.changes.DraftApi;
-import com.google.gerrit.extensions.api.changes.DraftInput;
-import com.google.gerrit.extensions.api.changes.NotifyHandling;
-import com.google.gerrit.extensions.api.changes.NotifyInfo;
-import com.google.gerrit.extensions.api.changes.RecipientType;
-import com.google.gerrit.extensions.api.changes.ReviewInput;
-import com.google.gerrit.extensions.api.changes.ReviewInput.CommentInput;
-import com.google.gerrit.extensions.api.changes.RevisionApi;
-import com.google.gerrit.extensions.api.projects.BranchInput;
-import com.google.gerrit.extensions.client.ChangeStatus;
-import com.google.gerrit.extensions.client.ReviewerState;
-import com.google.gerrit.extensions.client.SubmitType;
-import com.google.gerrit.extensions.common.AccountInfo;
-import com.google.gerrit.extensions.common.ApprovalInfo;
-import com.google.gerrit.extensions.common.ChangeInfo;
-import com.google.gerrit.extensions.common.ChangeMessageInfo;
-import com.google.gerrit.extensions.common.CommentInfo;
-import com.google.gerrit.extensions.common.CommitInfo;
-import com.google.gerrit.extensions.common.FileInfo;
-import com.google.gerrit.extensions.common.GitPerson;
-import com.google.gerrit.extensions.common.LabelInfo;
-import com.google.gerrit.extensions.common.MergeableInfo;
-import com.google.gerrit.extensions.common.RevisionInfo;
-import com.google.gerrit.extensions.common.WebLinkInfo;
-import com.google.gerrit.extensions.registration.DynamicSet;
-import com.google.gerrit.extensions.restapi.AuthException;
-import com.google.gerrit.extensions.restapi.BadRequestException;
-import com.google.gerrit.extensions.restapi.BinaryResult;
-import com.google.gerrit.extensions.restapi.ETagView;
-import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
-import com.google.gerrit.extensions.restapi.ResourceConflictException;
-import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
-import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
-import com.google.gerrit.extensions.webui.PatchSetWebLink;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.Branch;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.PatchSetApproval;
-import com.google.gerrit.server.change.GetRevisionActions;
-import com.google.gerrit.server.change.RevisionResource;
-import com.google.gerrit.server.query.change.ChangeData;
-import com.google.inject.Inject;
-import java.io.ByteArrayOutputStream;
-import java.sql.Timestamp;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Optional;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.RefUpdate;
-import org.eclipse.jgit.revwalk.RevCommit;
-import org.eclipse.jgit.transport.RefSpec;
-import org.junit.Test;
-
-public class RevisionIT extends AbstractDaemonTest {
-
- @Inject private GetRevisionActions getRevisionActions;
- @Inject private DynamicSet<PatchSetWebLink> patchSetLinks;
-
- @Test
- public void reviewTriplet() throws Exception {
- PushOneCommit.Result r = createChange();
- gApi.changes()
- .id(project.get() + "~master~" + r.getChangeId())
- .revision(r.getCommit().name())
- .review(ReviewInput.approve());
- }
-
- @Test
- public void reviewCurrent() throws Exception {
- PushOneCommit.Result r = createChange();
- gApi.changes().id(r.getChangeId()).current().review(ReviewInput.approve());
- }
-
- @Test
- public void reviewNumber() throws Exception {
- PushOneCommit.Result r = createChange();
- gApi.changes().id(r.getChangeId()).revision(1).review(ReviewInput.approve());
-
- r = updateChange(r, "new content");
- gApi.changes().id(r.getChangeId()).revision(2).review(ReviewInput.approve());
- }
-
- @Test
- public void submit() throws Exception {
- PushOneCommit.Result r = createChange();
- String changeId = project.get() + "~master~" + r.getChangeId();
- gApi.changes().id(changeId).current().review(ReviewInput.approve());
- gApi.changes().id(changeId).current().submit();
- assertThat(gApi.changes().id(changeId).get().status).isEqualTo(ChangeStatus.MERGED);
- }
-
- @Test
- public void postSubmitApproval() throws Exception {
- PushOneCommit.Result r = createChange();
- String changeId = project.get() + "~master~" + r.getChangeId();
- gApi.changes().id(changeId).current().review(ReviewInput.recommend());
-
- String label = "Code-Review";
- ApprovalInfo approval = getApproval(changeId, label);
- assertThat(approval.value).isEqualTo(1);
- assertThat(approval.postSubmit).isNull();
-
- // Submit by direct push.
- git().push().setRefSpecs(new RefSpec(r.getCommit().name() + ":refs/heads/master")).call();
- assertThat(gApi.changes().id(changeId).get().status).isEqualTo(ChangeStatus.MERGED);
-
- approval = getApproval(changeId, label);
- assertThat(approval.value).isEqualTo(1);
- assertThat(approval.postSubmit).isNull();
- assertPermitted(gApi.changes().id(changeId).get(DETAILED_LABELS), "Code-Review", 1, 2);
-
- // Repeating the current label is allowed. Does not flip the postSubmit bit
- // due to deduplication codepath.
- gApi.changes().id(changeId).current().review(ReviewInput.recommend());
- approval = getApproval(changeId, label);
- assertThat(approval.value).isEqualTo(1);
- assertThat(approval.postSubmit).isNull();
-
- // Reducing vote is not allowed.
- try {
- gApi.changes().id(changeId).current().review(ReviewInput.dislike());
- fail("expected ResourceConflictException");
- } catch (ResourceConflictException e) {
- assertThat(e)
- .hasMessageThat()
- .isEqualTo("Cannot reduce vote on labels for closed change: Code-Review");
- }
- approval = getApproval(changeId, label);
- assertThat(approval.value).isEqualTo(1);
- assertThat(approval.postSubmit).isNull();
-
- // Increasing vote is allowed.
- gApi.changes().id(changeId).current().review(ReviewInput.approve());
- approval = getApproval(changeId, label);
- assertThat(approval.value).isEqualTo(2);
- assertThat(approval.postSubmit).isTrue();
- assertPermitted(gApi.changes().id(changeId).get(DETAILED_LABELS), "Code-Review", 2);
-
- // Decreasing to previous post-submit vote is still not allowed.
- try {
- gApi.changes().id(changeId).current().review(ReviewInput.dislike());
- fail("expected ResourceConflictException");
- } catch (ResourceConflictException e) {
- assertThat(e)
- .hasMessageThat()
- .isEqualTo("Cannot reduce vote on labels for closed change: Code-Review");
- }
- approval = getApproval(changeId, label);
- assertThat(approval.value).isEqualTo(2);
- assertThat(approval.postSubmit).isTrue();
- }
-
- @Test
- public void postSubmitApprovalAfterVoteRemoved() throws Exception {
- PushOneCommit.Result r = createChange();
- String changeId = project.get() + "~master~" + r.getChangeId();
-
- setApiUser(admin);
- revision(r).review(ReviewInput.approve());
-
- setApiUser(user);
- revision(r).review(ReviewInput.recommend());
-
- setApiUser(admin);
- gApi.changes().id(changeId).reviewer(user.username).deleteVote("Code-Review");
- Optional<ApprovalInfo> crUser =
- get(changeId, DETAILED_LABELS).labels.get("Code-Review").all.stream()
- .filter(a -> a._accountId == user.id.get())
- .findFirst();
- assertThat(crUser).isPresent();
- assertThat(crUser.get().value).isEqualTo(0);
-
- revision(r).submit();
-
- setApiUser(user);
- ReviewInput in = new ReviewInput();
- in.label("Code-Review", 1);
- in.message = "Still LGTM";
- revision(r).review(in);
-
- ApprovalInfo cr =
- gApi.changes().id(changeId).get(DETAILED_LABELS).labels.get("Code-Review").all.stream()
- .filter(a -> a._accountId == user.getId().get())
- .findFirst()
- .get();
- assertThat(cr.postSubmit).isTrue();
- }
-
- @Test
- public void postSubmitDeleteApprovalNotAllowed() throws Exception {
- PushOneCommit.Result r = createChange();
-
- revision(r).review(ReviewInput.approve());
- revision(r).submit();
-
- ReviewInput in = new ReviewInput();
- in.label("Code-Review", 0);
-
- exception.expect(ResourceConflictException.class);
- exception.expectMessage("Cannot reduce vote on labels for closed change: Code-Review");
- revision(r).review(in);
- }
-
- @TestProjectInput(submitType = SubmitType.CHERRY_PICK)
- @Test
- public void approvalCopiedDuringSubmitIsNotPostSubmit() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getChange().getId();
- gApi.changes().id(id.get()).current().review(ReviewInput.approve());
- gApi.changes().id(id.get()).current().submit();
-
- ChangeData cd = r.getChange();
- assertThat(cd.patchSets()).hasSize(2);
- PatchSetApproval psa =
- Iterators.getOnlyElement(
- cd.currentApprovals().stream().filter(a -> !a.isLegacySubmit()).iterator());
- assertThat(psa.getPatchSetId().get()).isEqualTo(2);
- assertThat(psa.getLabel()).isEqualTo("Code-Review");
- assertThat(psa.getValue()).isEqualTo(2);
- assertThat(psa.isPostSubmit()).isFalse();
- }
-
- @Test
- public void voteOnAbandonedChange() throws Exception {
- PushOneCommit.Result r = createChange();
- gApi.changes().id(r.getChangeId()).abandon();
- exception.expect(ResourceConflictException.class);
- exception.expectMessage("change is closed");
- gApi.changes().id(r.getChangeId()).current().review(ReviewInput.reject());
- }
-
- @Test
- public void voteNotAllowedWithoutPermission() throws Exception {
- PushOneCommit.Result r = createChange();
- setApiUser(user);
- exception.expect(AuthException.class);
- exception.expectMessage("is restricted");
- gApi.changes().id(r.getChange().getId().get()).current().review(ReviewInput.approve());
- }
-
- @Test
- public void cherryPick() throws Exception {
- PushOneCommit.Result r = pushTo("refs/for/master%topic=someTopic");
- CherryPickInput in = new CherryPickInput();
- in.destination = "foo";
- in.message = "it goes to stable branch";
- gApi.projects().name(project.get()).branch(in.destination).create(new BranchInput());
- ChangeApi orig = gApi.changes().id(project.get() + "~master~" + r.getChangeId());
-
- assertThat(orig.get().messages).hasSize(1);
- ChangeApi cherry = orig.revision(r.getCommit().name()).cherryPick(in);
-
- ChangeInfo changeInfoWithDetails =
- gApi.changes().id(project.get() + "~master~" + r.getChangeId()).get();
- Collection<ChangeMessageInfo> messages = changeInfoWithDetails.messages;
- assertThat(messages).hasSize(2);
-
- String cherryPickedRevision = cherry.get().currentRevision;
- String expectedMessage =
- String.format(
- "Patch Set 1: Cherry Picked\n\n"
- + "This patchset was cherry picked to branch %s as commit %s",
- in.destination, cherryPickedRevision);
-
- Iterator<ChangeMessageInfo> origIt = messages.iterator();
- origIt.next();
- assertThat(origIt.next().message).isEqualTo(expectedMessage);
-
- ChangeInfo cherryPickChangeInfoWithDetails = cherry.get();
- assertThat(cherryPickChangeInfoWithDetails.workInProgress).isNull();
- assertThat(cherryPickChangeInfoWithDetails.messages).hasSize(1);
- Iterator<ChangeMessageInfo> cherryIt = cherryPickChangeInfoWithDetails.messages.iterator();
- expectedMessage = "Patch Set 1: Cherry Picked from branch master.";
- assertThat(cherryIt.next().message).isEqualTo(expectedMessage);
-
- assertThat(cherry.get().subject).contains(in.message);
- assertThat(cherry.get().topic).isEqualTo("someTopic-foo");
- cherry.current().review(ReviewInput.approve());
- cherry.current().submit();
- }
-
- @Test
- public void cherryPickSetChangeId() throws Exception {
- PushOneCommit.Result r = pushTo("refs/for/master");
- CherryPickInput in = new CherryPickInput();
- in.destination = "foo";
- String id = "Ideadbeefdeadbeefdeadbeefdeadbeefdeadbe3f";
- in.message = "it goes to foo branch\n\nChange-Id: " + id;
-
- gApi.projects().name(project.get()).branch(in.destination).create(new BranchInput());
- ChangeApi orig = gApi.changes().id(project.get() + "~master~" + r.getChangeId());
-
- assertThat(orig.get().messages).hasSize(1);
- ChangeApi cherry = orig.revision(r.getCommit().name()).cherryPick(in);
-
- ChangeInfo changeInfo = cherry.get();
-
- // The cherry-pick honors the ChangeId specified in the input message:
- RevisionInfo revInfo = changeInfo.revisions.get(changeInfo.currentRevision);
- assertThat(revInfo).isNotNull();
- assertThat(revInfo.commit.message).endsWith(id + "\n");
- }
-
- @Test
- public void cherryPickwithNoTopic() throws Exception {
- PushOneCommit.Result r = pushTo("refs/for/master");
- CherryPickInput in = new CherryPickInput();
- in.destination = "foo";
- in.message = "it goes to stable branch";
- gApi.projects().name(project.get()).branch(in.destination).create(new BranchInput());
- ChangeApi orig = gApi.changes().id(project.get() + "~master~" + r.getChangeId());
-
- ChangeApi cherry = orig.revision(r.getCommit().name()).cherryPick(in);
- assertThat(cherry.get().topic).isNull();
- cherry.current().review(ReviewInput.approve());
- cherry.current().submit();
- }
-
- @Test
- public void cherryPickWorkInProgressChange() throws Exception {
- PushOneCommit.Result r = pushTo("refs/for/master%wip");
- CherryPickInput in = new CherryPickInput();
- in.destination = "foo";
- in.message = "cherry pick message";
- gApi.projects().name(project.get()).branch(in.destination).create(new BranchInput());
- ChangeApi orig = gApi.changes().id(project.get() + "~master~" + r.getChangeId());
-
- ChangeApi cherry = orig.revision(r.getCommit().name()).cherryPick(in);
- assertThat(cherry.get().workInProgress).isTrue();
- }
-
- @Test
- public void cherryPickToSameBranch() throws Exception {
- PushOneCommit.Result r = createChange();
- CherryPickInput in = new CherryPickInput();
- in.destination = "master";
- in.message = "it generates a new patch set\n\nChange-Id: " + r.getChangeId();
- ChangeInfo cherryInfo =
- gApi.changes()
- .id(project.get() + "~master~" + r.getChangeId())
- .revision(r.getCommit().name())
- .cherryPick(in)
- .get();
- assertThat(cherryInfo.messages).hasSize(2);
- Iterator<ChangeMessageInfo> cherryIt = cherryInfo.messages.iterator();
- assertThat(cherryIt.next().message).isEqualTo("Uploaded patch set 1.");
- assertThat(cherryIt.next().message).isEqualTo("Uploaded patch set 2.");
- }
-
- @Test
- public void cherryPickToSameBranchWithRebase() throws Exception {
- // Push a new change, then merge it
- PushOneCommit.Result baseChange = createChange();
- String triplet = project.get() + "~master~" + baseChange.getChangeId();
- RevisionApi baseRevision = gApi.changes().id(triplet).current();
- baseRevision.review(ReviewInput.approve());
- baseRevision.submit();
-
- // Push a new change (change 1)
- PushOneCommit.Result r1 = createChange();
-
- // Push another new change (change 2)
- String subject = "Test change\n\nChange-Id: Ideadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
- PushOneCommit push =
- pushFactory.create(
- db, admin.getIdent(), testRepo, subject, "another_file.txt", "another content");
- PushOneCommit.Result r2 = push.to("refs/for/master");
-
- // Change 2's parent should be change 1
- assertThat(r2.getCommit().getParents()[0].name()).isEqualTo(r1.getCommit().name());
-
- // Cherry pick change 2 onto the same branch
- triplet = project.get() + "~master~" + r2.getChangeId();
- ChangeApi orig = gApi.changes().id(triplet);
- CherryPickInput in = new CherryPickInput();
- in.destination = "master";
- in.message = subject;
- ChangeApi cherry = orig.revision(r2.getCommit().name()).cherryPick(in);
- ChangeInfo cherryInfo = cherry.get();
- assertThat(cherryInfo.messages).hasSize(2);
- Iterator<ChangeMessageInfo> cherryIt = cherryInfo.messages.iterator();
- assertThat(cherryIt.next().message).isEqualTo("Uploaded patch set 1.");
- assertThat(cherryIt.next().message).isEqualTo("Uploaded patch set 2.");
-
- // Parent of change 2 should now be the change that was merged, i.e.
- // change 2 is rebased onto the head of the master branch.
- String newParent =
- cherryInfo.revisions.get(cherryInfo.currentRevision).commit.parents.get(0).commit;
- assertThat(newParent).isEqualTo(baseChange.getCommit().name());
- }
-
- @Test
- public void cherryPickIdenticalTree() throws Exception {
- PushOneCommit.Result r = createChange();
- CherryPickInput in = new CherryPickInput();
- in.destination = "foo";
- in.message = "it goes to stable branch";
- gApi.projects().name(project.get()).branch(in.destination).create(new BranchInput());
- ChangeApi orig = gApi.changes().id(project.get() + "~master~" + r.getChangeId());
-
- assertThat(orig.get().messages).hasSize(1);
- ChangeApi cherry = orig.revision(r.getCommit().name()).cherryPick(in);
-
- Collection<ChangeMessageInfo> messages =
- gApi.changes().id(project.get() + "~master~" + r.getChangeId()).get().messages;
- assertThat(messages).hasSize(2);
-
- assertThat(cherry.get().subject).contains(in.message);
- cherry.current().review(ReviewInput.approve());
- cherry.current().submit();
-
- exception.expect(ResourceConflictException.class);
- exception.expectMessage("Cherry pick failed: identical tree");
- orig.revision(r.getCommit().name()).cherryPick(in);
- }
-
- @Test
- public void cherryPickConflict() throws Exception {
- PushOneCommit.Result r = createChange();
- CherryPickInput in = new CherryPickInput();
- in.destination = "foo";
- in.message = "it goes to stable branch";
- gApi.projects().name(project.get()).branch(in.destination).create(new BranchInput());
-
- PushOneCommit push =
- pushFactory.create(
- db,
- admin.getIdent(),
- testRepo,
- PushOneCommit.SUBJECT,
- PushOneCommit.FILE_NAME,
- "another content");
- push.to("refs/heads/foo");
-
- String triplet = project.get() + "~master~" + r.getChangeId();
- ChangeApi orig = gApi.changes().id(triplet);
- assertThat(orig.get().messages).hasSize(1);
-
- exception.expect(ResourceConflictException.class);
- exception.expectMessage("Cherry pick failed: merge conflict");
- orig.revision(r.getCommit().name()).cherryPick(in);
- }
-
- @Test
- public void cherryPickToExistingChange() throws Exception {
- PushOneCommit.Result r1 =
- pushFactory
- .create(db, admin.getIdent(), testRepo, SUBJECT, FILE_NAME, "a")
- .to("refs/for/master");
- String t1 = project.get() + "~master~" + r1.getChangeId();
-
- BranchInput bin = new BranchInput();
- bin.revision = r1.getCommit().getParent(0).name();
- gApi.projects().name(project.get()).branch("foo").create(bin);
-
- PushOneCommit.Result r2 =
- pushFactory
- .create(db, admin.getIdent(), testRepo, SUBJECT, FILE_NAME, "b", r1.getChangeId())
- .to("refs/for/foo");
- String t2 = project.get() + "~foo~" + r2.getChangeId();
- gApi.changes().id(t2).abandon();
-
- CherryPickInput in = new CherryPickInput();
- in.destination = "foo";
- in.message = r1.getCommit().getFullMessage();
- try {
- gApi.changes().id(t1).current().cherryPick(in);
- fail();
- } catch (ResourceConflictException e) {
- assertThat(e.getMessage())
- .isEqualTo(
- "Cannot create new patch set of change "
- + info(t2)._number
- + " because it is abandoned");
- }
-
- gApi.changes().id(t2).restore();
- gApi.changes().id(t1).current().cherryPick(in);
- assertThat(get(t2).revisions).hasSize(2);
- assertThat(gApi.changes().id(t2).current().file(FILE_NAME).content().asString()).isEqualTo("a");
- }
-
- @Test
- public void cherryPickMergeRelativeToDefaultParent() throws Exception {
- String parent1FileName = "a.txt";
- String parent2FileName = "b.txt";
- PushOneCommit.Result mergeChangeResult =
- createCherryPickableMerge(parent1FileName, parent2FileName);
-
- String cherryPickBranchName = "branch_for_cherry_pick";
- createBranch(new Branch.NameKey(project, cherryPickBranchName));
-
- CherryPickInput cherryPickInput = new CherryPickInput();
- cherryPickInput.destination = cherryPickBranchName;
- cherryPickInput.message = "Cherry-pick a merge commit to another branch";
-
- ChangeInfo cherryPickedChangeInfo =
- gApi.changes()
- .id(mergeChangeResult.getChangeId())
- .current()
- .cherryPick(cherryPickInput)
- .get();
-
- Map<String, FileInfo> cherryPickedFilesByName =
- cherryPickedChangeInfo.revisions.get(cherryPickedChangeInfo.currentRevision).files;
- assertThat(cherryPickedFilesByName).containsKey(parent2FileName);
- assertThat(cherryPickedFilesByName).doesNotContainKey(parent1FileName);
- }
-
- @Test
- public void cherryPickMergeRelativeToSpecificParent() throws Exception {
- String parent1FileName = "a.txt";
- String parent2FileName = "b.txt";
- PushOneCommit.Result mergeChangeResult =
- createCherryPickableMerge(parent1FileName, parent2FileName);
-
- String cherryPickBranchName = "branch_for_cherry_pick";
- createBranch(new Branch.NameKey(project, cherryPickBranchName));
-
- CherryPickInput cherryPickInput = new CherryPickInput();
- cherryPickInput.destination = cherryPickBranchName;
- cherryPickInput.message = "Cherry-pick a merge commit to another branch";
- cherryPickInput.parent = 2;
-
- ChangeInfo cherryPickedChangeInfo =
- gApi.changes()
- .id(mergeChangeResult.getChangeId())
- .current()
- .cherryPick(cherryPickInput)
- .get();
-
- Map<String, FileInfo> cherryPickedFilesByName =
- cherryPickedChangeInfo.revisions.get(cherryPickedChangeInfo.currentRevision).files;
- assertThat(cherryPickedFilesByName).containsKey(parent1FileName);
- assertThat(cherryPickedFilesByName).doesNotContainKey(parent2FileName);
- }
-
- @Test
- public void cherryPickMergeUsingInvalidParent() throws Exception {
- String parent1FileName = "a.txt";
- String parent2FileName = "b.txt";
- PushOneCommit.Result mergeChangeResult =
- createCherryPickableMerge(parent1FileName, parent2FileName);
-
- String cherryPickBranchName = "branch_for_cherry_pick";
- createBranch(new Branch.NameKey(project, cherryPickBranchName));
-
- CherryPickInput cherryPickInput = new CherryPickInput();
- cherryPickInput.destination = cherryPickBranchName;
- cherryPickInput.message = "Cherry-pick a merge commit to another branch";
- cherryPickInput.parent = 0;
-
- exception.expect(BadRequestException.class);
- exception.expectMessage(
- "Cherry Pick: Parent 0 does not exist. Please specify a parent in range [1, 2].");
- gApi.changes().id(mergeChangeResult.getChangeId()).current().cherryPick(cherryPickInput);
- }
-
- @Test
- public void cherryPickMergeUsingNonExistentParent() throws Exception {
- String parent1FileName = "a.txt";
- String parent2FileName = "b.txt";
- PushOneCommit.Result mergeChangeResult =
- createCherryPickableMerge(parent1FileName, parent2FileName);
-
- String cherryPickBranchName = "branch_for_cherry_pick";
- createBranch(new Branch.NameKey(project, cherryPickBranchName));
-
- CherryPickInput cherryPickInput = new CherryPickInput();
- cherryPickInput.destination = cherryPickBranchName;
- cherryPickInput.message = "Cherry-pick a merge commit to another branch";
- cherryPickInput.parent = 3;
-
- exception.expect(BadRequestException.class);
- exception.expectMessage(
- "Cherry Pick: Parent 3 does not exist. Please specify a parent in range [1, 2].");
- gApi.changes().id(mergeChangeResult.getChangeId()).current().cherryPick(cherryPickInput);
- }
-
- @Test
- public void cherryPickNotify() throws Exception {
- createBranch(new Branch.NameKey(project, "branch-1"));
- createBranch(new Branch.NameKey(project, "branch-2"));
- createBranch(new Branch.NameKey(project, "branch-3"));
-
- // Creates a change for 'admin'.
- PushOneCommit.Result result = createChange();
- String changeId = project.get() + "~master~" + result.getChangeId();
-
- // 'user' cherry-picks the change to a new branch, the source change's author/committer('admin')
- // will be added as a reviewer of the newly created change.
- setApiUser(user);
- CherryPickInput input = new CherryPickInput();
- input.message = "it goes to a new branch";
-
- // Enable the notification. 'admin' as a reviewer should be notified.
- input.destination = "branch-1";
- input.notify = NotifyHandling.ALL;
- sender.clear();
- gApi.changes().id(changeId).current().cherryPick(input);
- assertNotifyCc(admin);
-
- // Disable the notification. 'admin' as a reviewer should not be notified any more.
- input.destination = "branch-2";
- input.notify = NotifyHandling.NONE;
- sender.clear();
- gApi.changes().id(changeId).current().cherryPick(input);
- assertThat(sender.getMessages()).hasSize(0);
-
- // Disable the notification. The user provided in the 'notifyDetails' should still be notified.
- TestAccount userToNotify = accountCreator.user2();
- input.destination = "branch-3";
- input.notify = NotifyHandling.NONE;
- input.notifyDetails =
- ImmutableMap.of(RecipientType.TO, new NotifyInfo(ImmutableList.of(userToNotify.email)));
- sender.clear();
- gApi.changes().id(changeId).current().cherryPick(input);
- assertNotifyTo(userToNotify);
- }
-
- @Test
- public void cherryPickKeepReviewers() throws Exception {
- createBranch(new Branch.NameKey(project, "stable"));
-
- // Change is created by 'admin'.
- PushOneCommit.Result r = createChange();
- // Change is approved by 'admin2'. Change is CC'd to 'user'.
- setApiUser(accountCreator.admin2());
- ReviewInput in = ReviewInput.approve();
- in.reviewer(user.email, ReviewerState.CC, true);
- gApi.changes().id(r.getChangeId()).current().review(in);
-
- // Change is cherrypicked by 'user2'.
- setApiUser(accountCreator.user2());
- CherryPickInput cin = new CherryPickInput();
- cin.message = "this need to go to stable";
- cin.destination = "stable";
- cin.keepReviewers = true;
- Map<ReviewerState, Collection<AccountInfo>> result =
- gApi.changes().id(r.getChangeId()).current().cherryPick(cin).get().reviewers;
-
- // 'admin' should be a reviewer as the old owner.
- // 'admin2' should be a reviewer as the old reviewer.
- // 'user' should be on CC.
- assertThat(result).containsKey(ReviewerState.REVIEWER);
- List<Integer> reviewers =
- result.get(ReviewerState.REVIEWER).stream().map(a -> a._accountId).collect(toList());
- if (notesMigration.readChanges()) {
- assertThat(result).containsKey(ReviewerState.CC);
- List<Integer> ccs =
- result.get(ReviewerState.CC).stream().map(a -> a._accountId).collect(toList());
- assertThat(ccs).containsExactly(user.id.get());
- assertThat(reviewers).containsExactly(admin.id.get(), accountCreator.admin2().id.get());
- } else {
- assertThat(reviewers)
- .containsExactly(user.id.get(), admin.id.get(), accountCreator.admin2().id.get());
- }
- }
-
- @Test
- public void cherryPickToMergedChangeRevision() throws Exception {
- createBranch(new Branch.NameKey(project, "foo"));
-
- PushOneCommit.Result dstChange = createChange(testRepo, "foo", SUBJECT, "b.txt", "b", "t");
- dstChange.assertOkStatus();
-
- merge(dstChange);
-
- PushOneCommit.Result result = createChange(testRepo, "foo", SUBJECT, "b.txt", "c", "t");
- result.assertOkStatus();
- merge(result);
-
- PushOneCommit.Result srcChange = createChange();
-
- CherryPickInput input = new CherryPickInput();
- input.destination = "foo";
- input.base = dstChange.getCommit().name();
- input.message = srcChange.getCommit().getFullMessage();
- ChangeInfo changeInfo =
- gApi.changes().id(srcChange.getChangeId()).current().cherryPick(input).get();
- assertCherryPickResult(changeInfo, input, srcChange.getChangeId());
- }
-
- @Test
- public void cherryPickToOpenChangeRevision() throws Exception {
- createBranch(new Branch.NameKey(project, "foo"));
-
- PushOneCommit.Result dstChange = createChange(testRepo, "foo", SUBJECT, "b.txt", "b", "t");
- dstChange.assertOkStatus();
-
- PushOneCommit.Result srcChange = createChange();
-
- CherryPickInput input = new CherryPickInput();
- input.destination = "foo";
- input.base = dstChange.getCommit().name();
- input.message = srcChange.getCommit().getFullMessage();
- ChangeInfo changeInfo =
- gApi.changes().id(srcChange.getChangeId()).current().cherryPick(input).get();
- assertCherryPickResult(changeInfo, input, srcChange.getChangeId());
- }
-
- @Test
- public void cherryPickToNonVisibleChangeFails() throws Exception {
- createBranch(new Branch.NameKey(project, "foo"));
-
- PushOneCommit.Result dstChange = createChange(testRepo, "foo", SUBJECT, "b.txt", "b", "t");
- dstChange.assertOkStatus();
-
- gApi.changes().id(dstChange.getChangeId()).setPrivate(true, null);
-
- PushOneCommit.Result srcChange = createChange();
-
- CherryPickInput input = new CherryPickInput();
- input.destination = "foo";
- input.base = dstChange.getCommit().name();
- input.message = srcChange.getCommit().getFullMessage();
-
- setApiUser(user);
- exception.expect(UnprocessableEntityException.class);
- exception.expectMessage(
- String.format("Commit %s does not exist on branch refs/heads/foo", input.base));
- gApi.changes().id(srcChange.getChangeId()).current().cherryPick(input).get();
- }
-
- @Test
- public void cherryPickToAbandonedChangeFails() throws Exception {
- PushOneCommit.Result change1 = createChange();
- PushOneCommit.Result change2 = createChange();
- gApi.changes().id(change2.getChangeId()).abandon();
-
- CherryPickInput input = new CherryPickInput();
- input.destination = "master";
- input.base = change2.getCommit().name();
- input.message = change1.getCommit().getFullMessage();
-
- exception.expect(ResourceConflictException.class);
- exception.expectMessage(
- String.format(
- "Change %s with commit %s is %s",
- change2.getChange().getId().get(), input.base, ChangeStatus.ABANDONED));
- gApi.changes().id(change1.getChangeId()).current().cherryPick(input);
- }
-
- @Test
- public void cherryPickWithInvalidBaseFails() throws Exception {
- PushOneCommit.Result change1 = createChange();
-
- CherryPickInput input = new CherryPickInput();
- input.destination = "master";
- input.base = "invalid-sha1";
- input.message = change1.getCommit().getFullMessage();
-
- exception.expect(BadRequestException.class);
- exception.expectMessage(String.format("Base %s doesn't represent a valid SHA-1", input.base));
- gApi.changes().id(change1.getChangeId()).current().cherryPick(input);
- }
-
- @Test
- public void cherryPickToCommitWithoutChangeId() throws Exception {
- RevCommit commit1 = createNewCommitWithoutChangeId("refs/heads/foo", "a.txt", "content 1");
-
- createNewCommitWithoutChangeId("refs/heads/foo", "a.txt", "content 2");
-
- PushOneCommit.Result srcChange = createChange("subject", "b.txt", "b");
- srcChange.assertOkStatus();
-
- CherryPickInput input = new CherryPickInput();
- input.destination = "foo";
- input.base = commit1.name();
- input.message = srcChange.getCommit().getFullMessage();
- ChangeInfo changeInfo =
- gApi.changes().id(srcChange.getChangeId()).current().cherryPick(input).get();
- assertCherryPickResult(changeInfo, input, srcChange.getChangeId());
- }
-
- @Test
- public void canRebase() throws Exception {
- PushOneCommit push = pushFactory.create(db, admin.getIdent(), testRepo);
- PushOneCommit.Result r1 = push.to("refs/for/master");
- merge(r1);
-
- push = pushFactory.create(db, admin.getIdent(), testRepo);
- PushOneCommit.Result r2 = push.to("refs/for/master");
- boolean canRebase =
- gApi.changes().id(r2.getChangeId()).revision(r2.getCommit().name()).canRebase();
- assertThat(canRebase).isFalse();
- merge(r2);
-
- testRepo.reset(r1.getCommit());
- push = pushFactory.create(db, admin.getIdent(), testRepo);
- PushOneCommit.Result r3 = push.to("refs/for/master");
-
- canRebase = gApi.changes().id(r3.getChangeId()).revision(r3.getCommit().name()).canRebase();
- assertThat(canRebase).isTrue();
- }
-
- @Test
- public void setUnsetReviewedFlag() throws Exception {
- PushOneCommit push = pushFactory.create(db, admin.getIdent(), testRepo);
- PushOneCommit.Result r = push.to("refs/for/master");
-
- gApi.changes().id(r.getChangeId()).current().setReviewed(PushOneCommit.FILE_NAME, true);
-
- assertThat(Iterables.getOnlyElement(gApi.changes().id(r.getChangeId()).current().reviewed()))
- .isEqualTo(PushOneCommit.FILE_NAME);
-
- gApi.changes().id(r.getChangeId()).current().setReviewed(PushOneCommit.FILE_NAME, false);
-
- assertThat(gApi.changes().id(r.getChangeId()).current().reviewed()).isEmpty();
- }
-
- @Test
- public void setUnsetReviewedFlagByFileApi() throws Exception {
- PushOneCommit push = pushFactory.create(db, admin.getIdent(), testRepo);
- PushOneCommit.Result r = push.to("refs/for/master");
-
- gApi.changes().id(r.getChangeId()).current().file(PushOneCommit.FILE_NAME).setReviewed(true);
-
- assertThat(Iterables.getOnlyElement(gApi.changes().id(r.getChangeId()).current().reviewed()))
- .isEqualTo(PushOneCommit.FILE_NAME);
-
- gApi.changes().id(r.getChangeId()).current().file(PushOneCommit.FILE_NAME).setReviewed(false);
-
- assertThat(gApi.changes().id(r.getChangeId()).current().reviewed()).isEmpty();
- }
-
- @Test
- public void mergeable() throws Exception {
- ObjectId initial = repo().exactRef(HEAD).getLeaf().getObjectId();
-
- PushOneCommit push1 =
- pushFactory.create(
- db,
- admin.getIdent(),
- testRepo,
- PushOneCommit.SUBJECT,
- PushOneCommit.FILE_NAME,
- "push 1 content");
-
- PushOneCommit.Result r1 = push1.to("refs/for/master");
- assertMergeable(r1.getChangeId(), true);
- merge(r1);
-
- // Reset HEAD to initial so the new change is a merge conflict.
- RefUpdate ru = repo().updateRef(HEAD);
- ru.setNewObjectId(initial);
- assertThat(ru.forceUpdate()).isEqualTo(RefUpdate.Result.FORCED);
-
- PushOneCommit push2 =
- pushFactory.create(
- db,
- admin.getIdent(),
- testRepo,
- PushOneCommit.SUBJECT,
- PushOneCommit.FILE_NAME,
- "push 2 content");
- PushOneCommit.Result r2 = push2.to("refs/for/master");
- assertMergeable(r2.getChangeId(), false);
- // TODO(dborowitz): Test for other-branches.
- }
-
- @Test
- public void files() throws Exception {
- PushOneCommit.Result r = createChange();
- Map<String, FileInfo> files =
- gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).files();
- assertThat(files).hasSize(2);
- assertThat(Iterables.all(files.keySet(), f -> f.matches(FILE_NAME + '|' + COMMIT_MSG)))
- .isTrue();
- }
-
- @Test
- public void filesOnMergeCommitChange() throws Exception {
- PushOneCommit.Result r = createMergeCommitChange("refs/for/master");
-
- // list files against auto-merge
- assertThat(gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).files().keySet())
- .containsExactly(COMMIT_MSG, MERGE_LIST, "foo", "bar");
-
- // list files against parent 1
- assertThat(gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).files(1).keySet())
- .containsExactly(COMMIT_MSG, MERGE_LIST, "bar");
-
- // list files against parent 2
- assertThat(gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).files(2).keySet())
- .containsExactly(COMMIT_MSG, MERGE_LIST, "foo");
- }
-
- @Test
- public void listFilesOnDifferentBases() throws Exception {
- PushOneCommit.Result result1 = createChange();
- String changeId = result1.getChangeId();
- PushOneCommit.Result result2 = amendChange(changeId, SUBJECT, "b.txt", "b");
- PushOneCommit.Result result3 = amendChange(changeId, SUBJECT, "c.txt", "c");
-
- String revId1 = result1.getCommit().name();
- String revId2 = result2.getCommit().name();
- String revId3 = result3.getCommit().name();
-
- assertThat(gApi.changes().id(changeId).revision(revId1).files(null).keySet())
- .containsExactly(COMMIT_MSG, "a.txt");
- assertThat(gApi.changes().id(changeId).revision(revId2).files(null).keySet())
- .containsExactly(COMMIT_MSG, "a.txt", "b.txt");
- assertThat(gApi.changes().id(changeId).revision(revId3).files(null).keySet())
- .containsExactly(COMMIT_MSG, "a.txt", "b.txt", "c.txt");
-
- assertThat(gApi.changes().id(changeId).revision(revId2).files(revId1).keySet())
- .containsExactly(COMMIT_MSG, "b.txt");
- assertThat(gApi.changes().id(changeId).revision(revId3).files(revId1).keySet())
- .containsExactly(COMMIT_MSG, "b.txt", "c.txt");
- assertThat(gApi.changes().id(changeId).revision(revId3).files(revId2).keySet())
- .containsExactly(COMMIT_MSG, "c.txt");
- }
-
- @Test
- public void queryRevisionFiles() throws Exception {
- Map<String, String> files = ImmutableMap.of("file1.txt", "content 1", "file2.txt", "content 2");
- PushOneCommit.Result result =
- pushFactory.create(db, admin.getIdent(), testRepo, SUBJECT, files).to("refs/for/master");
- result.assertOkStatus();
- String changeId = result.getChangeId();
-
- assertThat(gApi.changes().id(changeId).current().queryFiles("file1.txt"))
- .containsExactly("file1.txt");
- assertThat(gApi.changes().id(changeId).current().queryFiles("file2.txt"))
- .containsExactly("file2.txt");
- assertThat(gApi.changes().id(changeId).current().queryFiles("file1"))
- .containsExactly("file1.txt");
- assertThat(gApi.changes().id(changeId).current().queryFiles("file2"))
- .containsExactly("file2.txt");
- assertThat(gApi.changes().id(changeId).current().queryFiles("file"))
- .containsExactly("file1.txt", "file2.txt");
- assertThat(gApi.changes().id(changeId).current().queryFiles(""))
- .containsExactly("file1.txt", "file2.txt");
- }
-
- @Test
- public void description() throws Exception {
- PushOneCommit.Result r = createChange();
- assertDescription(r, "");
- gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).description("test");
- assertDescription(r, "test");
- gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).description("");
- assertDescription(r, "");
- }
-
- @Test
- public void setDescriptionNotAllowedWithoutPermission() throws Exception {
- PushOneCommit.Result r = createChange();
- assertDescription(r, "");
- setApiUser(user);
- exception.expect(AuthException.class);
- exception.expectMessage("edit description not permitted");
- gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).description("test");
- }
-
- @Test
- public void setDescriptionAllowedWithPermission() throws Exception {
- PushOneCommit.Result r = createChange();
- assertDescription(r, "");
- grant(project, "refs/heads/master", Permission.OWNER, false, REGISTERED_USERS);
- setApiUser(user);
- gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).description("test");
- assertDescription(r, "test");
- }
-
- private void assertDescription(PushOneCommit.Result r, String expected) throws Exception {
- assertThat(gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).description())
- .isEqualTo(expected);
- }
-
- @Test
- public void content() throws Exception {
- PushOneCommit.Result r = createChange();
- assertContent(r, FILE_NAME, FILE_CONTENT);
- assertContent(r, COMMIT_MSG, r.getCommit().getFullMessage());
- }
-
- @Test
- public void contentType() throws Exception {
- PushOneCommit.Result r = createChange();
-
- String endPoint =
- "/changes/"
- + r.getChangeId()
- + "/revisions/"
- + r.getCommit().name()
- + "/files/"
- + FILE_NAME
- + "/content";
- RestResponse response = adminRestSession.head(endPoint);
- response.assertOK();
- assertThat(response.getContentType()).startsWith("text/plain");
- assertThat(response.hasContent()).isFalse();
- }
-
- @Test
- public void commit() throws Exception {
- WebLinkInfo expectedWebLinkInfo = new WebLinkInfo("foo", "imageUrl", "url");
- patchSetLinks.add(
- new PatchSetWebLink() {
- @Override
- public WebLinkInfo getPatchSetWebLink(String projectName, String commit) {
- return expectedWebLinkInfo;
- }
- });
-
- PushOneCommit.Result r = createChange();
- RevCommit c = r.getCommit();
-
- CommitInfo commitInfo = gApi.changes().id(r.getChangeId()).current().commit(false);
- assertThat(commitInfo.commit).isEqualTo(c.name());
- assertPersonIdent(commitInfo.author, c.getAuthorIdent());
- assertPersonIdent(commitInfo.committer, c.getCommitterIdent());
- assertThat(commitInfo.message).isEqualTo(c.getFullMessage());
- assertThat(commitInfo.subject).isEqualTo(c.getShortMessage());
- assertThat(commitInfo.parents).hasSize(1);
- assertThat(Iterables.getOnlyElement(commitInfo.parents).commit)
- .isEqualTo(c.getParent(0).name());
- assertThat(commitInfo.webLinks).isNull();
-
- commitInfo = gApi.changes().id(r.getChangeId()).current().commit(true);
- assertThat(commitInfo.webLinks).hasSize(1);
- WebLinkInfo webLinkInfo = Iterables.getOnlyElement(commitInfo.webLinks);
- assertThat(webLinkInfo.name).isEqualTo(expectedWebLinkInfo.name);
- assertThat(webLinkInfo.imageUrl).isEqualTo(expectedWebLinkInfo.imageUrl);
- assertThat(webLinkInfo.url).isEqualTo(expectedWebLinkInfo.url);
- assertThat(webLinkInfo.target).isEqualTo(expectedWebLinkInfo.target);
- }
-
- private void assertPersonIdent(GitPerson gitPerson, PersonIdent expectedIdent) {
- assertThat(gitPerson.name).isEqualTo(expectedIdent.getName());
- assertThat(gitPerson.email).isEqualTo(expectedIdent.getEmailAddress());
- assertThat(gitPerson.date).isEqualTo(new Timestamp(expectedIdent.getWhen().getTime()));
- assertThat(gitPerson.tz).isEqualTo(expectedIdent.getTimeZoneOffset());
- }
-
- private void assertMergeable(String id, boolean expected) throws Exception {
- MergeableInfo m = gApi.changes().id(id).current().mergeable();
- assertThat(m.mergeable).isEqualTo(expected);
- assertThat(m.submitType).isEqualTo(SubmitType.MERGE_IF_NECESSARY);
- assertThat(m.mergeableInto).isNull();
- ChangeInfo c = gApi.changes().id(id).info();
- assertThat(c.mergeable).isEqualTo(expected);
- }
-
- @Test
- public void drafts() throws Exception {
- PushOneCommit.Result r = createChange();
- DraftInput in = new DraftInput();
- in.line = 1;
- in.message = "nit: trailing whitespace";
- in.path = FILE_NAME;
-
- DraftApi draftApi =
- gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).createDraft(in);
- assertThat(draftApi.get().message).isEqualTo(in.message);
- assertThat(
- gApi.changes()
- .id(r.getChangeId())
- .revision(r.getCommit().name())
- .draft(draftApi.get().id)
- .get()
- .message)
- .isEqualTo(in.message);
- assertThat(gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).drafts())
- .hasSize(1);
-
- in.message = "good catch!";
- assertThat(
- gApi.changes()
- .id(r.getChangeId())
- .revision(r.getCommit().name())
- .draft(draftApi.get().id)
- .update(in)
- .message)
- .isEqualTo(in.message);
-
- assertThat(
- gApi.changes()
- .id(r.getChangeId())
- .revision(r.getCommit().name())
- .draft(draftApi.get().id)
- .get()
- .author
- .email)
- .isEqualTo(admin.email);
-
- draftApi.delete();
- assertThat(gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).drafts())
- .isEmpty();
- }
-
- @Test
- public void comments() throws Exception {
- PushOneCommit.Result r = createChange();
- CommentInput in = new CommentInput();
- in.line = 1;
- in.message = "nit: trailing whitespace";
- in.path = FILE_NAME;
- ReviewInput reviewInput = new ReviewInput();
- Map<String, List<CommentInput>> comments = new HashMap<>();
- comments.put(FILE_NAME, Collections.singletonList(in));
- reviewInput.comments = comments;
- reviewInput.message = "comment test";
- gApi.changes().id(r.getChangeId()).current().review(reviewInput);
-
- Map<String, List<CommentInfo>> out =
- gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).comments();
- assertThat(out).hasSize(1);
- CommentInfo comment = Iterables.getOnlyElement(out.get(FILE_NAME));
- assertThat(comment.message).isEqualTo(in.message);
- assertThat(comment.author.email).isEqualTo(admin.email);
- assertThat(comment.path).isNull();
-
- List<CommentInfo> list =
- gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).commentsAsList();
- assertThat(list).hasSize(1);
-
- CommentInfo comment2 = list.get(0);
- assertThat(comment2.path).isEqualTo(FILE_NAME);
- assertThat(comment2.line).isEqualTo(comment.line);
- assertThat(comment2.message).isEqualTo(comment.message);
- assertThat(comment2.author.email).isEqualTo(comment.author.email);
-
- assertThat(
- gApi.changes()
- .id(r.getChangeId())
- .revision(r.getCommit().name())
- .comment(comment.id)
- .get()
- .message)
- .isEqualTo(in.message);
- }
-
- @Test
- public void commentOnNonExistingFile() throws Exception {
- PushOneCommit.Result r = createChange();
- r = updateChange(r, "new content");
- CommentInput in = new CommentInput();
- in.line = 1;
- in.message = "nit: trailing whitespace";
- in.path = "non-existing.txt";
- ReviewInput reviewInput = new ReviewInput();
- Map<String, List<CommentInput>> comments = new HashMap<>();
- comments.put("non-existing.txt", Collections.singletonList(in));
- reviewInput.comments = comments;
- reviewInput.message = "comment test";
-
- exception.expect(BadRequestException.class);
- exception.expectMessage(
- String.format("not found in revision %d,1", r.getChange().change().getId().id));
- gApi.changes().id(r.getChangeId()).revision(1).review(reviewInput);
- }
-
- @Test
- public void patch() throws Exception {
- PushOneCommit.Result r = createChange();
- ChangeApi changeApi = gApi.changes().id(r.getChangeId());
- BinaryResult bin = changeApi.revision(r.getCommit().name()).patch();
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- bin.writeTo(os);
- String res = new String(os.toByteArray(), UTF_8);
- ChangeInfo change = changeApi.get();
- RevisionInfo rev = change.revisions.get(change.currentRevision);
- DateFormat df = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);
- String date = df.format(rev.commit.author.date);
- assertThat(res).isEqualTo(String.format(PATCH, r.getCommit().name(), date, r.getChangeId()));
- }
-
- @Test
- public void patchWithPath() throws Exception {
- PushOneCommit.Result r = createChange();
- ChangeApi changeApi = gApi.changes().id(r.getChangeId());
- BinaryResult bin = changeApi.revision(r.getCommit().name()).patch(FILE_NAME);
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- bin.writeTo(os);
- String res = new String(os.toByteArray(), UTF_8);
- assertThat(res).isEqualTo(PATCH_FILE_ONLY);
-
- exception.expect(ResourceNotFoundException.class);
- exception.expectMessage("File not found: nonexistent-file.");
- changeApi.revision(r.getCommit().name()).patch("nonexistent-file");
- }
-
- @Test
- public void actions() throws Exception {
- PushOneCommit.Result r = createChange();
- assertThat(current(r).actions().keySet())
- .containsExactly("cherrypick", "description", "rebase");
-
- current(r).review(ReviewInput.approve());
- assertThat(current(r).actions().keySet())
- .containsExactly("submit", "cherrypick", "description", "rebase");
-
- current(r).submit();
- assertThat(current(r).actions().keySet()).containsExactly("cherrypick");
- }
-
- @Test
- public void actionsETag() throws Exception {
- PushOneCommit.Result r1 = createChange();
- PushOneCommit.Result r2 = createChange();
-
- String oldETag = checkETag(getRevisionActions, r2, null);
- current(r2).review(ReviewInput.approve());
- oldETag = checkETag(getRevisionActions, r2, oldETag);
-
- // Dependent change is included in ETag.
- current(r1).review(ReviewInput.approve());
- oldETag = checkETag(getRevisionActions, r2, oldETag);
-
- current(r2).submit();
- oldETag = checkETag(getRevisionActions, r2, oldETag);
- }
-
- @Test
- public void deleteVoteOnNonCurrentPatchSet() throws Exception {
- PushOneCommit.Result r = createChange(); // patch set 1
- gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).review(ReviewInput.approve());
-
- // patch set 2
- amendChange(r.getChangeId());
-
- // code-review
- setApiUser(user);
- recommend(r.getChangeId());
-
- // check if it's blocked to delete a vote on a non-current patch set.
- setApiUser(admin);
- exception.expect(MethodNotAllowedException.class);
- exception.expectMessage("Cannot access on non-current patch set");
- gApi.changes()
- .id(r.getChangeId())
- .revision(r.getCommit().getName())
- .reviewer(user.getId().toString())
- .deleteVote("Code-Review");
- }
-
- @Test
- public void deleteVoteOnCurrentPatchSet() throws Exception {
- PushOneCommit.Result r = createChange(); // patch set 1
- gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).review(ReviewInput.approve());
-
- // patch set 2
- amendChange(r.getChangeId());
-
- // code-review
- setApiUser(user);
- recommend(r.getChangeId());
-
- setApiUser(admin);
- gApi.changes()
- .id(r.getChangeId())
- .current()
- .reviewer(user.getId().toString())
- .deleteVote("Code-Review");
-
- Map<String, Short> m =
- gApi.changes().id(r.getChangeId()).current().reviewer(user.getId().toString()).votes();
-
- assertThat(m).containsExactly("Code-Review", Short.valueOf((short) 0));
-
- ChangeInfo c = gApi.changes().id(r.getChangeId()).get();
- ChangeMessageInfo message = Iterables.getLast(c.messages);
- assertThat(message.author._accountId).isEqualTo(admin.getId().get());
- assertThat(message.message).isEqualTo("Removed Code-Review+1 by User <user@example.com>\n");
- assertThat(getReviewers(c.reviewers.get(ReviewerState.REVIEWER)))
- .containsExactlyElementsIn(ImmutableSet.of(admin.getId(), user.getId()));
- }
-
- @Test
- public void listVotesByRevision() throws Exception {
- // Create patch set 1 and vote on it
- String changeId = createChange().getChangeId();
- ListMultimap<String, ApprovalInfo> votes = gApi.changes().id(changeId).current().votes();
- assertThat(votes).isEmpty();
- recommend(changeId);
- votes = gApi.changes().id(changeId).current().votes();
- assertThat(votes.keySet()).containsExactly("Code-Review");
- List<ApprovalInfo> approvals = votes.get("Code-Review");
- assertThat(approvals).hasSize(1);
- ApprovalInfo approval = approvals.get(0);
- assertThat(approval._accountId).isEqualTo(admin.id.get());
- assertThat(approval.email).isEqualTo(admin.email);
- assertThat(approval.username).isEqualTo(admin.username);
-
- // Also vote on it with another user
- setApiUser(user);
- gApi.changes().id(changeId).current().review(ReviewInput.dislike());
-
- // Patch set 1 has 2 votes on Code-Review
- setApiUser(admin);
- votes = gApi.changes().id(changeId).current().votes();
- assertThat(votes.keySet()).containsExactly("Code-Review");
- approvals = votes.get("Code-Review");
- assertThat(approvals).hasSize(2);
- assertThat(approvals.stream().map(a -> a._accountId))
- .containsExactlyElementsIn(ImmutableList.of(admin.id.get(), user.id.get()));
-
- // Create a new patch set which does not have any votes
- amendChange(changeId);
- votes = gApi.changes().id(changeId).current().votes();
- assertThat(votes).isEmpty();
-
- // Votes are still returned for ps 1
- votes = gApi.changes().id(changeId).revision(1).votes();
- assertThat(votes.keySet()).containsExactly("Code-Review");
- approvals = votes.get("Code-Review");
- assertThat(approvals).hasSize(2);
- }
-
- private static void assertCherryPickResult(
- ChangeInfo changeInfo, CherryPickInput input, String srcChangeId) throws Exception {
- assertThat(changeInfo.changeId).isEqualTo(srcChangeId);
- assertThat(changeInfo.revisions.keySet()).containsExactly(changeInfo.currentRevision);
- RevisionInfo revisionInfo = changeInfo.revisions.get(changeInfo.currentRevision);
- assertThat(revisionInfo.commit.message).isEqualTo(input.message);
- assertThat(revisionInfo.commit.parents).hasSize(1);
- assertThat(revisionInfo.commit.parents.get(0).commit).isEqualTo(input.base);
- }
-
- private PushOneCommit.Result updateChange(PushOneCommit.Result r, String content)
- throws Exception {
- PushOneCommit push =
- pushFactory.create(
- db, admin.getIdent(), testRepo, "test commit", "a.txt", content, r.getChangeId());
- return push.to("refs/for/master");
- }
-
- private RevisionApi current(PushOneCommit.Result r) throws Exception {
- return gApi.changes().id(r.getChangeId()).current();
- }
-
- private String checkETag(ETagView<RevisionResource> view, PushOneCommit.Result r, String oldETag)
- throws Exception {
- String eTag = view.getETag(parseRevisionResource(r));
- assertThat(eTag).isNotEqualTo(oldETag);
- return eTag;
- }
-
- private PushOneCommit.Result createCherryPickableMerge(
- String parent1FileName, String parent2FileName) throws Exception {
- RevCommit initialCommit = getHead(repo());
-
- String branchAName = "branchA";
- createBranch(new Branch.NameKey(project, branchAName));
- String branchBName = "branchB";
- createBranch(new Branch.NameKey(project, branchBName));
-
- PushOneCommit.Result changeAResult =
- pushFactory
- .create(db, admin.getIdent(), testRepo, "change a", parent1FileName, "Content of a")
- .to("refs/for/" + branchAName);
-
- testRepo.reset(initialCommit);
- PushOneCommit.Result changeBResult =
- pushFactory
- .create(db, admin.getIdent(), testRepo, "change b", parent2FileName, "Content of b")
- .to("refs/for/" + branchBName);
-
- PushOneCommit pushableMergeCommit =
- pushFactory.create(
- db,
- admin.getIdent(),
- testRepo,
- "merge",
- ImmutableMap.of(parent1FileName, "Content of a", parent2FileName, "Content of b"));
- pushableMergeCommit.setParents(
- ImmutableList.of(changeAResult.getCommit(), changeBResult.getCommit()));
- PushOneCommit.Result mergeChangeResult = pushableMergeCommit.to("refs/for/" + branchAName);
- mergeChangeResult.assertOkStatus();
- return mergeChangeResult;
- }
-
- private ApprovalInfo getApproval(String changeId, String label) throws Exception {
- ChangeInfo info = gApi.changes().id(changeId).get(DETAILED_LABELS);
- LabelInfo li = info.labels.get(label);
- assertThat(li).isNotNull();
- int accountId = atrScope.get().getUser().getAccountId().get();
- return li.all.stream().filter(a -> a._accountId == accountId).findFirst().get();
- }
-
- private static Iterable<Account.Id> getReviewers(Collection<AccountInfo> r) {
- return Iterables.transform(r, a -> new Account.Id(a._accountId));
- }
-}