Discontinue draft workflow
Migration is implemented to either replace draft changes with private (default) or work-in-progress changes. We bump the change index version to trigger online reindexing. That's needed because we don't support reindexing during init step, and we need to reindex all changes, because DRAFT is removed from the Change.Status enum and index still contains the old references to the changes that were migrated to private or work-in-progress changes. To make online reindexing work, draft status is replaced with the new change status. PolyGerrit UI is not addressed in this change and will be done in a follow-up change. User branches are not updated in this change to clean-up My-Menu entry in user preferences. This will be done in a follow-up change. refs/meta/config is not updated in this change to clean-up draft related permissions. This will be done in a follow-up change. ChangeControl#isPatchVisible() call sites are migrated to the ChangeControl#isVisible() and isVisible() is made public again. This and other temporary changes to ChangeControl class will be cleaned up in follow up changes. Bug: Issue 6880 Change-Id: Icfcb34efe1ff0ea1d39e94ed500db776f5770d8f
This commit is contained in:
committed by
Changcheng Xiao
parent
80522c3e22
commit
6ffb7d9358
@@ -73,7 +73,7 @@ public class GeneralPreferencesIT extends AbstractDaemonTest {
|
||||
public void getAndSetPreferences() throws Exception {
|
||||
GeneralPreferencesInfo o = gApi.accounts().id(user42.id.toString()).getPreferences();
|
||||
assertPrefs(o, GeneralPreferencesInfo.defaults(), "my", "changeTable");
|
||||
assertThat(o.my).hasSize(7);
|
||||
assertThat(o.my).hasSize(6);
|
||||
assertThat(o.changeTable).isEmpty();
|
||||
|
||||
GeneralPreferencesInfo i = GeneralPreferencesInfo.defaults();
|
||||
|
||||
@@ -98,17 +98,6 @@ public class AbandonIT extends AbstractDaemonTest {
|
||||
changeAbandoner.batchAbandon(batchUpdateFactory, new Project.NameKey(project1Name), user, list);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void abandonDraft() throws Exception {
|
||||
PushOneCommit.Result r = createDraftChange();
|
||||
String changeId = r.getChangeId();
|
||||
assertThat(info(changeId).status).isEqualTo(ChangeStatus.DRAFT);
|
||||
|
||||
exception.expect(ResourceConflictException.class);
|
||||
exception.expectMessage("draft changes cannot be abandoned");
|
||||
gApi.changes().id(changeId).abandon();
|
||||
}
|
||||
|
||||
@Test
|
||||
@GerritConfig(name = "changeCleanup.abandonAfter", value = "1w")
|
||||
public void abandonInactiveOpenChanges() throws Exception {
|
||||
|
||||
@@ -835,23 +835,6 @@ public class ChangeIT extends AbstractDaemonTest {
|
||||
gApi.changes().id(changeId).rebase();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void publish() throws Exception {
|
||||
PushOneCommit.Result r = createDraftChange();
|
||||
assertThat(info(r.getChangeId()).status).isEqualTo(ChangeStatus.DRAFT);
|
||||
gApi.changes().id(r.getChangeId()).publish();
|
||||
assertThat(info(r.getChangeId()).status).isEqualTo(ChangeStatus.NEW);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteDraftChange() throws Exception {
|
||||
PushOneCommit.Result r = createDraftChange();
|
||||
assertThat(query(r.getChangeId())).hasSize(1);
|
||||
assertThat(info(r.getChangeId()).status).isEqualTo(ChangeStatus.DRAFT);
|
||||
gApi.changes().id(r.getChangeId()).delete();
|
||||
assertThat(query(r.getChangeId())).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteNewChangeAsAdmin() throws Exception {
|
||||
PushOneCommit.Result changeResult = createChange();
|
||||
@@ -2311,7 +2294,6 @@ public class ChangeIT extends AbstractDaemonTest {
|
||||
gApi.changes().id(r1.getChangeId()).revision(r1.getCommit().name()).submit();
|
||||
|
||||
createChange();
|
||||
createDraftChange();
|
||||
|
||||
setApiUser(user);
|
||||
AcceptanceTestRequestScope.Context ctx = disableDb();
|
||||
@@ -2462,64 +2444,6 @@ public class ChangeIT extends AbstractDaemonTest {
|
||||
gApi.changes().create(in).get();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createNewPatchSetOnVisibleDraftPatchSet() throws Exception {
|
||||
// Clone separate repositories of the same project as admin and as user
|
||||
TestRepository<InMemoryRepository> adminTestRepo = cloneProject(project, admin);
|
||||
TestRepository<InMemoryRepository> userTestRepo = cloneProject(project, user);
|
||||
|
||||
// Create change as admin
|
||||
PushOneCommit push = pushFactory.create(db, admin.getIdent(), adminTestRepo);
|
||||
PushOneCommit.Result r1 = push.to("refs/for/master");
|
||||
r1.assertOkStatus();
|
||||
|
||||
// Amend draft as admin
|
||||
PushOneCommit.Result r2 =
|
||||
amendChange(r1.getChangeId(), "refs/for/master", admin, adminTestRepo);
|
||||
r2.assertOkStatus();
|
||||
setCurrentPatchSetAsDraft(r2.getChange().getId());
|
||||
|
||||
// Add user as reviewer to make this patch set visible
|
||||
AddReviewerInput in = new AddReviewerInput();
|
||||
in.reviewer = user.email;
|
||||
gApi.changes().id(r1.getChangeId()).addReviewer(in);
|
||||
|
||||
// Fetch change
|
||||
GitUtil.fetch(userTestRepo, r2.getPatchSet().getRefName() + ":ps");
|
||||
userTestRepo.reset("ps");
|
||||
|
||||
// Amend change as user
|
||||
PushOneCommit.Result r3 = amendChange(r2.getChangeId(), "refs/for/master", user, userTestRepo);
|
||||
r3.assertOkStatus();
|
||||
setCurrentPatchSetAsDraft(r3.getChange().getId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createNewPatchSetOnInvisibleDraftPatchSet() throws Exception {
|
||||
// Clone separate repositories of the same project as admin and as user
|
||||
TestRepository<InMemoryRepository> adminTestRepo = cloneProject(project, admin);
|
||||
TestRepository<InMemoryRepository> userTestRepo = cloneProject(project, user);
|
||||
|
||||
// Create change as admin
|
||||
PushOneCommit push = pushFactory.create(db, admin.getIdent(), adminTestRepo);
|
||||
PushOneCommit.Result r1 = push.to("refs/for/master");
|
||||
r1.assertOkStatus();
|
||||
|
||||
// Amend draft as admin
|
||||
PushOneCommit.Result r2 =
|
||||
amendChange(r1.getChangeId(), "refs/for/master", admin, adminTestRepo);
|
||||
r2.assertOkStatus();
|
||||
setCurrentPatchSetAsDraft(r2.getChange().getId());
|
||||
|
||||
// Fetch change
|
||||
GitUtil.fetch(userTestRepo, r1.getPatchSet().getRefName() + ":ps");
|
||||
userTestRepo.reset("ps");
|
||||
|
||||
// Amend change as user
|
||||
PushOneCommit.Result r3 = amendChange(r1.getChangeId(), "refs/for/master", user, userTestRepo);
|
||||
r3.assertErrorStatus("cannot add patch set to " + r3.getChange().change().getChangeId() + ".");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createNewPatchSetWithoutPermission() throws Exception {
|
||||
// Create new project with clean permissions
|
||||
@@ -2591,63 +2515,6 @@ public class ChangeIT extends AbstractDaemonTest {
|
||||
r2.assertOkStatus();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createNewPatchSetAsReviewerOnDraftChange() throws Exception {
|
||||
// Clone separate repositories of the same project as admin and as user
|
||||
TestRepository<?> adminTestRepo = cloneProject(project, admin);
|
||||
TestRepository<?> userTestRepo = cloneProject(project, user);
|
||||
|
||||
// Create change as admin
|
||||
PushOneCommit push = pushFactory.create(db, admin.getIdent(), adminTestRepo);
|
||||
PushOneCommit.Result r1 = push.to("refs/for/master");
|
||||
r1.assertOkStatus();
|
||||
markChangeAsDraft(r1.getChange().getId());
|
||||
|
||||
// Add user as reviewer
|
||||
AddReviewerInput in = new AddReviewerInput();
|
||||
in.reviewer = user.email;
|
||||
gApi.changes().id(r1.getChangeId()).addReviewer(in);
|
||||
|
||||
// Fetch change
|
||||
GitUtil.fetch(userTestRepo, r1.getPatchSet().getRefName() + ":ps");
|
||||
userTestRepo.reset("ps");
|
||||
|
||||
// Amend change as user
|
||||
PushOneCommit.Result r2 = amendChange(r1.getChangeId(), "refs/for/master", user, userTestRepo);
|
||||
r2.assertOkStatus();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createNewDraftPatchSetOnDraftChange() throws Exception {
|
||||
// Create new project with clean permissions
|
||||
Project.NameKey p = createProject("addPatchSet4");
|
||||
// Clone separate repositories of the same project as admin and as user
|
||||
TestRepository<?> adminTestRepo = cloneProject(p, admin);
|
||||
TestRepository<?> userTestRepo = cloneProject(p, user);
|
||||
|
||||
// Block default permission
|
||||
block(p, "refs/for/*", Permission.ADD_PATCH_SET, REGISTERED_USERS);
|
||||
|
||||
// Create change as admin
|
||||
PushOneCommit push = pushFactory.create(db, admin.getIdent(), adminTestRepo);
|
||||
PushOneCommit.Result r1 = push.to("refs/for/master");
|
||||
r1.assertOkStatus();
|
||||
markChangeAsDraft(p, r1.getChange().getId());
|
||||
|
||||
// Add user as reviewer
|
||||
AddReviewerInput in = new AddReviewerInput();
|
||||
in.reviewer = user.email;
|
||||
gApi.changes().id(r1.getChangeId()).addReviewer(in);
|
||||
|
||||
// Fetch change
|
||||
GitUtil.fetch(userTestRepo, r1.getPatchSet().getRefName() + ":ps");
|
||||
userTestRepo.reset("ps");
|
||||
|
||||
// Amend change as user
|
||||
PushOneCommit.Result r2 = amendChange(r1.getChangeId(), "refs/for/master", user, userTestRepo);
|
||||
r2.assertErrorStatus("cannot add patch set to " + r1.getChange().getId().id + ".");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createMergePatchSet() throws Exception {
|
||||
PushOneCommit.Result start = pushTo("refs/heads/master");
|
||||
|
||||
@@ -301,12 +301,6 @@ public class RevisionIT extends AbstractDaemonTest {
|
||||
gApi.changes().id(r.getChange().getId().get()).current().review(ReviewInput.approve());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteDraft() throws Exception {
|
||||
PushOneCommit.Result r = createDraftChange();
|
||||
gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).delete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cherryPick() throws Exception {
|
||||
PushOneCommit.Result r = pushTo("refs/for/master%topic=someTopic");
|
||||
|
||||
@@ -42,6 +42,7 @@ import com.google.gerrit.acceptance.AbstractDaemonTest;
|
||||
import com.google.gerrit.acceptance.GerritConfig;
|
||||
import com.google.gerrit.acceptance.GitUtil;
|
||||
import com.google.gerrit.acceptance.PushOneCommit;
|
||||
import com.google.gerrit.acceptance.Sandboxed;
|
||||
import com.google.gerrit.acceptance.TestAccount;
|
||||
import com.google.gerrit.acceptance.TestProjectInput;
|
||||
import com.google.gerrit.common.data.LabelType;
|
||||
@@ -61,6 +62,7 @@ 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.EditInfo;
|
||||
import com.google.gerrit.extensions.common.EditInfoSubject;
|
||||
import com.google.gerrit.extensions.common.LabelInfo;
|
||||
import com.google.gerrit.extensions.common.RevisionInfo;
|
||||
import com.google.gerrit.reviewdb.client.AccountGroup;
|
||||
@@ -636,34 +638,6 @@ public abstract class AbstractPushForReview extends AbstractDaemonTest {
|
||||
r.assertOkStatus();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pushForMasterAsDraft() throws Exception {
|
||||
// create draft by pushing to 'refs/drafts/' will get a private change.
|
||||
PushOneCommit.Result r = pushTo("refs/drafts/master");
|
||||
r.assertOkStatus();
|
||||
r.assertChange(Change.Status.NEW, null);
|
||||
|
||||
assertThat(gApi.changes().id(r.getChangeId()).get().isPrivate).isTrue();
|
||||
|
||||
// create draft by using 'draft' option will get a private change, too.
|
||||
r = pushTo("refs/for/master%draft");
|
||||
r.assertOkStatus();
|
||||
r.assertChange(Change.Status.NEW, null);
|
||||
assertThat(gApi.changes().id(r.getChangeId()).get().isPrivate).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void publishDraftChangeByPushingNonDraftPatchSet() throws Exception {
|
||||
PushOneCommit.Result r = createDraftChange();
|
||||
r.assertOkStatus();
|
||||
r.assertChange(Change.Status.DRAFT, null);
|
||||
|
||||
// publish draft change by pushing non-draft patch set
|
||||
r = amendChange(r.getChangeId(), "refs/for/master");
|
||||
r.assertOkStatus();
|
||||
r.assertChange(Change.Status.NEW, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pushForMasterAsEdit() throws Exception {
|
||||
PushOneCommit.Result r = pushTo("refs/for/master");
|
||||
@@ -1819,6 +1793,42 @@ public abstract class AbstractPushForReview extends AbstractDaemonTest {
|
||||
assertThat(getPublishedComments(r.getChangeId())).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pushDraftGetsPrivateChange() throws Exception {
|
||||
String changeId1 = createChange("refs/drafts/master").getChangeId();
|
||||
String changeId2 = createChange("refs/for/master%draft").getChangeId();
|
||||
|
||||
ChangeInfo info1 = gApi.changes().id(changeId1).get();
|
||||
ChangeInfo info2 = gApi.changes().id(changeId2).get();
|
||||
|
||||
assertThat(info1.status).isEqualTo(ChangeStatus.NEW);
|
||||
assertThat(info2.status).isEqualTo(ChangeStatus.NEW);
|
||||
assertThat(info1.isPrivate).isEqualTo(true);
|
||||
assertThat(info2.isPrivate).isEqualTo(true);
|
||||
assertThat(info1.revisions).hasSize(1);
|
||||
assertThat(info2.revisions).hasSize(1);
|
||||
}
|
||||
|
||||
@Sandboxed
|
||||
@Test
|
||||
public void pushWithDraftOptionToExistingNewChangeGetsChangeEdit() throws Exception {
|
||||
String changeId = createChange().getChangeId();
|
||||
EditInfoSubject.assertThat(getEdit(changeId)).isAbsent();
|
||||
|
||||
ChangeInfo changeInfo = gApi.changes().id(changeId).get();
|
||||
ChangeStatus originalChangeStatus = changeInfo.status;
|
||||
|
||||
PushOneCommit.Result result = amendChange(changeId, "refs/drafts/master");
|
||||
result.assertOkStatus();
|
||||
|
||||
changeInfo = gApi.changes().id(changeId).get();
|
||||
assertThat(changeInfo.status).isEqualTo(originalChangeStatus);
|
||||
assertThat(changeInfo.isPrivate).isNull();
|
||||
assertThat(changeInfo.revisions).hasSize(1);
|
||||
|
||||
EditInfoSubject.assertThat(getEdit(changeId)).isPresent();
|
||||
}
|
||||
|
||||
@GerritConfig(name = "receive.maxBatchCommits", value = "2")
|
||||
@Test
|
||||
public void maxBatchCommits() throws Exception {
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
// Copyright (C) 2014 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.git;
|
||||
|
||||
import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
|
||||
|
||||
import com.google.gerrit.acceptance.AbstractDaemonTest;
|
||||
import com.google.gerrit.acceptance.NoHttpd;
|
||||
import com.google.gerrit.acceptance.PushOneCommit;
|
||||
import com.google.gerrit.common.data.Permission;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
@NoHttpd
|
||||
public class DraftChangeBlockedIT extends AbstractDaemonTest {
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
block("refs/drafts/*", Permission.PUSH, ANONYMOUS_USERS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pushDraftChange_Blocked() throws Exception {
|
||||
// create draft by pushing to 'refs/drafts/'
|
||||
PushOneCommit.Result r = pushTo("refs/drafts/master");
|
||||
r.assertErrorStatus("cannot upload drafts");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pushDraftChangeMagic_Blocked() throws Exception {
|
||||
// create draft by using 'draft' option
|
||||
PushOneCommit.Result r = pushTo("refs/for/master%draft");
|
||||
r.assertErrorStatus("cannot upload drafts");
|
||||
}
|
||||
}
|
||||
@@ -319,53 +319,6 @@ public class RefAdvertisementIT extends AbstractDaemonTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void uploadPackDraftRefs() throws Exception {
|
||||
allow("refs/heads/*", Permission.READ, REGISTERED_USERS);
|
||||
|
||||
PushOneCommit.Result br = createDraftChange();
|
||||
br.assertOkStatus();
|
||||
Change.Id c5 = br.getChange().getId();
|
||||
String r5 = changeRefPrefix(c5);
|
||||
|
||||
// Only admin can see admin's draft change (5).
|
||||
setApiUser(admin);
|
||||
assertUploadPackRefs(
|
||||
"HEAD",
|
||||
r1 + "1",
|
||||
r1 + "meta",
|
||||
r2 + "1",
|
||||
r2 + "meta",
|
||||
r3 + "1",
|
||||
r3 + "meta",
|
||||
r4 + "1",
|
||||
r4 + "meta",
|
||||
r5 + "1",
|
||||
r5 + "meta",
|
||||
"refs/heads/branch",
|
||||
"refs/heads/master",
|
||||
RefNames.REFS_CONFIG,
|
||||
"refs/tags/branch-tag",
|
||||
"refs/tags/master-tag");
|
||||
|
||||
// user can't.
|
||||
setApiUser(user);
|
||||
assertUploadPackRefs(
|
||||
"HEAD",
|
||||
r1 + "1",
|
||||
r1 + "meta",
|
||||
r2 + "1",
|
||||
r2 + "meta",
|
||||
r3 + "1",
|
||||
r3 + "meta",
|
||||
r4 + "1",
|
||||
r4 + "meta",
|
||||
"refs/heads/branch",
|
||||
"refs/heads/master",
|
||||
"refs/tags/branch-tag",
|
||||
"refs/tags/master-tag");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void uploadPackNoSearchingChangeCacheImpl() throws Exception {
|
||||
allow("refs/heads/*", Permission.READ, REGISTERED_USERS);
|
||||
|
||||
@@ -169,12 +169,6 @@ public class SubmitOnPushIT extends AbstractDaemonTest {
|
||||
r.assertErrorStatus("update by submit not permitted");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void submitOnPushingDraft_Error() throws Exception {
|
||||
PushOneCommit.Result r = pushTo("refs/for/master%draft,submit");
|
||||
r.assertErrorStatus();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void submitOnPushToNonExistingBranch_Error() throws Exception {
|
||||
String branchName = "non-existing";
|
||||
|
||||
@@ -520,20 +520,6 @@ public abstract class AbstractSubmit extends AbstractDaemonTest {
|
||||
.containsExactlyElementsIn(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void submitDraftChange() throws Exception {
|
||||
PushOneCommit.Result draft = createDraftChange();
|
||||
Change.Id num = draft.getChange().getId();
|
||||
submitWithConflict(
|
||||
draft.getChangeId(),
|
||||
"Failed to submit 1 change due to the following problems:\n"
|
||||
+ "Change "
|
||||
+ num
|
||||
+ ": Change "
|
||||
+ num
|
||||
+ " is draft");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void submitWorkInProgressChange() throws Exception {
|
||||
PushOneCommit.Result change = createWorkInProgressChange();
|
||||
@@ -548,21 +534,6 @@ public abstract class AbstractSubmit extends AbstractDaemonTest {
|
||||
+ " is work in progress");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void submitDraftPatchSet() throws Exception {
|
||||
PushOneCommit.Result change = createChange();
|
||||
PushOneCommit.Result draft = amendChangeAndMarkPatchSetAsDraft(change.getChangeId());
|
||||
Change.Id num = draft.getChange().getId();
|
||||
|
||||
submitWithConflict(
|
||||
draft.getChangeId(),
|
||||
"Failed to submit 1 change due to the following problems:\n"
|
||||
+ "Change "
|
||||
+ num
|
||||
+ ": submit rule error: "
|
||||
+ "Cannot submit draft patch sets");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void submitWithHiddenBranchInSameTopic() throws Exception {
|
||||
assume().that(isSubmitWholeTopicEnabled()).isTrue();
|
||||
|
||||
@@ -139,28 +139,6 @@ public class ActionsIT extends AbstractDaemonTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void revisionActionsETagWithHiddenDraftInTopic() throws Exception {
|
||||
String change = createChangeWithTopic().getChangeId();
|
||||
approve(change);
|
||||
|
||||
setApiUser(user);
|
||||
String etag1 = getETag(change);
|
||||
|
||||
setApiUser(admin);
|
||||
String draft = createDraftChange("topic").getChangeId();
|
||||
approve(draft);
|
||||
|
||||
setApiUser(user);
|
||||
String etag2 = getETag(change);
|
||||
|
||||
if (isSubmitWholeTopicEnabled()) {
|
||||
assertThat(etag2).isNotEqualTo(etag1);
|
||||
} else {
|
||||
assertThat(etag2).isEqualTo(etag1);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void revisionActionsAnonymousETag() throws Exception {
|
||||
String parent = createChange().getChangeId();
|
||||
|
||||
@@ -276,19 +276,6 @@ public class ChangeReviewersByEmailIT extends AbstractDaemonTest {
|
||||
assertThat(result.reviewers).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rejectOnNonPublicChange() throws Exception {
|
||||
assume().that(notesMigration.readChanges()).isTrue();
|
||||
PushOneCommit.Result r = createDraftChange();
|
||||
|
||||
AddReviewerResult result =
|
||||
gApi.changes().id(r.getChangeId()).addReviewer("Foo Bar <foo.bar@gerritcodereview.com>");
|
||||
assertThat(result.error)
|
||||
.isEqualTo(
|
||||
"Foo Bar <foo.bar@gerritcodereview.com> does not have permission to see this change");
|
||||
assertThat(result.reviewers).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rejectWhenFeatureIsDisabled() throws Exception {
|
||||
assume().that(notesMigration.readChanges()).isTrue();
|
||||
|
||||
@@ -24,9 +24,7 @@ import static org.eclipse.jgit.lib.Constants.SIGNED_OFF_BY_TAG;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.gerrit.acceptance.AbstractDaemonTest;
|
||||
import com.google.gerrit.acceptance.GerritConfig;
|
||||
import com.google.gerrit.acceptance.PushOneCommit;
|
||||
import com.google.gerrit.acceptance.PushOneCommit.Result;
|
||||
import com.google.gerrit.acceptance.RestResponse;
|
||||
@@ -138,13 +136,6 @@ public class CreateChangeIT extends AbstractDaemonTest {
|
||||
"%sAdministrator <%s>", SIGNED_OFF_BY_TAG, admin.getIdent().getEmailAddress()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@GerritConfig(name = "change.allowDrafts", value = "true")
|
||||
public void createNewDraftChangeNotAllowed() throws Exception {
|
||||
ChangeInput ci = newChangeInput(ChangeStatus.DRAFT);
|
||||
assertCreateFails(ci, BadRequestException.class, "unsupported change status");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createNewPrivateChange() throws Exception {
|
||||
ChangeInput input = newChangeInput(ChangeStatus.NEW);
|
||||
@@ -388,9 +379,7 @@ public class CreateChangeIT extends AbstractDaemonTest {
|
||||
assertThat(out.workInProgress).isEqualTo(in.workInProgress);
|
||||
assertThat(out.revisions).hasSize(1);
|
||||
assertThat(out.submitted).isNull();
|
||||
assertThat(out.submitter).isNull();
|
||||
Boolean draft = Iterables.getOnlyElement(out.revisions.values()).draft;
|
||||
assertThat(booleanToDraftStatus(draft)).isEqualTo(in.status);
|
||||
assertThat(in.status).isEqualTo(ChangeStatus.NEW);
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -402,13 +391,6 @@ public class CreateChangeIT extends AbstractDaemonTest {
|
||||
gApi.changes().create(in);
|
||||
}
|
||||
|
||||
private ChangeStatus booleanToDraftStatus(Boolean draft) {
|
||||
if (draft == null) {
|
||||
return ChangeStatus.NEW;
|
||||
}
|
||||
return draft ? ChangeStatus.DRAFT : ChangeStatus.NEW;
|
||||
}
|
||||
|
||||
// TODO(davido): Expose setting of account preferences in the API
|
||||
private void setSignedOffByFooter() throws Exception {
|
||||
RestResponse r = adminRestSession.get("/accounts/" + admin.email + "/preferences");
|
||||
|
||||
@@ -1,261 +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.rest.change;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.gerrit.acceptance.AbstractDaemonTest;
|
||||
import com.google.gerrit.acceptance.NoHttpd;
|
||||
import com.google.gerrit.acceptance.PushOneCommit;
|
||||
import com.google.gerrit.acceptance.TestAccount;
|
||||
import com.google.gerrit.extensions.api.changes.DraftInput;
|
||||
import com.google.gerrit.extensions.api.changes.ReviewInput;
|
||||
import com.google.gerrit.extensions.api.changes.ReviewInput.CommentInput;
|
||||
import com.google.gerrit.extensions.client.ChangeStatus;
|
||||
import com.google.gerrit.extensions.client.Side;
|
||||
import com.google.gerrit.extensions.common.ChangeInfo;
|
||||
import com.google.gerrit.extensions.restapi.ResourceConflictException;
|
||||
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gerrit.reviewdb.client.ChangeMessage;
|
||||
import com.google.gerrit.reviewdb.client.Comment;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gerrit.reviewdb.client.RefNames;
|
||||
import com.google.gerrit.server.config.AllUsersName;
|
||||
import com.google.gerrit.server.query.change.ChangeData;
|
||||
import com.google.inject.Inject;
|
||||
import java.util.HashMap;
|
||||
import org.eclipse.jgit.lib.Ref;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.junit.Test;
|
||||
|
||||
@NoHttpd
|
||||
public class DeleteDraftPatchSetIT extends AbstractDaemonTest {
|
||||
|
||||
@Inject private AllUsersName allUsers;
|
||||
|
||||
@Test
|
||||
public void deletePatchSetNotDraft() throws Exception {
|
||||
String changeId = createChange().getChangeId();
|
||||
PatchSet ps = getCurrentPatchSet(changeId);
|
||||
String triplet = project.get() + "~master~" + changeId;
|
||||
ChangeInfo c = get(triplet);
|
||||
assertThat(c.id).isEqualTo(triplet);
|
||||
assertThat(c.status).isEqualTo(ChangeStatus.NEW);
|
||||
|
||||
exception.expect(ResourceConflictException.class);
|
||||
exception.expectMessage("Patch set is not a draft");
|
||||
setApiUser(admin);
|
||||
deletePatchSet(changeId, ps);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteDraftPatchSetNoACL() throws Exception {
|
||||
String changeId = createDraftChangeWith2PS();
|
||||
PatchSet ps = getCurrentPatchSet(changeId);
|
||||
String triplet = project.get() + "~master~" + changeId;
|
||||
ChangeInfo c = get(triplet);
|
||||
assertThat(c.id).isEqualTo(triplet);
|
||||
assertThat(c.status).isEqualTo(ChangeStatus.DRAFT);
|
||||
|
||||
exception.expect(ResourceNotFoundException.class);
|
||||
exception.expectMessage("Not found: " + changeId);
|
||||
setApiUser(user);
|
||||
deletePatchSet(changeId, ps);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteDraftPatchSetAndChange() throws Exception {
|
||||
String changeId = createDraftChangeWith2PS();
|
||||
PatchSet ps = getCurrentPatchSet(changeId);
|
||||
Change.Id id = ps.getId().getParentKey();
|
||||
|
||||
DraftInput din = new DraftInput();
|
||||
din.path = "a.txt";
|
||||
din.message = "comment on a.txt";
|
||||
gApi.changes().id(changeId).current().createDraft(din);
|
||||
|
||||
if (notesMigration.commitChangeWrites()) {
|
||||
assertThat(getDraftRef(admin, id)).isNotNull();
|
||||
}
|
||||
|
||||
ChangeData cd = getChange(changeId);
|
||||
assertThat(cd.patchSets()).hasSize(2);
|
||||
assertThat(cd.change().currentPatchSetId().get()).isEqualTo(2);
|
||||
assertThat(cd.change().getStatus()).isEqualTo(Change.Status.DRAFT);
|
||||
deletePatchSet(changeId, ps);
|
||||
|
||||
cd = getChange(changeId);
|
||||
assertThat(cd.patchSets()).hasSize(1);
|
||||
assertThat(cd.change().currentPatchSetId().get()).isEqualTo(1);
|
||||
|
||||
ps = getCurrentPatchSet(changeId);
|
||||
deletePatchSet(changeId, ps);
|
||||
assertThat(queryProvider.get().byKeyPrefix(changeId)).isEmpty();
|
||||
|
||||
if (notesMigration.commitChangeWrites()) {
|
||||
assertThat(getDraftRef(admin, id)).isNull();
|
||||
assertThat(getMetaRef(id)).isNull();
|
||||
}
|
||||
|
||||
exception.expect(ResourceNotFoundException.class);
|
||||
gApi.changes().id(id.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteDraftPS1() throws Exception {
|
||||
String changeId = createDraftChangeWith2PS();
|
||||
|
||||
ReviewInput rin = new ReviewInput();
|
||||
rin.message = "Change message";
|
||||
CommentInput cin = new CommentInput();
|
||||
cin.line = 1;
|
||||
cin.patchSet = 1;
|
||||
cin.path = PushOneCommit.FILE_NAME;
|
||||
cin.side = Side.REVISION;
|
||||
cin.message = "Inline comment";
|
||||
rin.comments = new HashMap<>();
|
||||
rin.comments.put(cin.path, ImmutableList.of(cin));
|
||||
gApi.changes().id(changeId).revision(1).review(rin);
|
||||
|
||||
ChangeData cd = getChange(changeId);
|
||||
PatchSet.Id delPsId = new PatchSet.Id(cd.getId(), 1);
|
||||
PatchSet ps = cd.patchSet(delPsId);
|
||||
deletePatchSet(changeId, ps);
|
||||
|
||||
cd = getChange(changeId);
|
||||
assertThat(cd.patchSets()).hasSize(1);
|
||||
assertThat(Iterables.getOnlyElement(cd.patchSets()).getId().get()).isEqualTo(2);
|
||||
|
||||
// Other entities based on deleted patch sets are also deleted.
|
||||
for (ChangeMessage m : cd.messages()) {
|
||||
assertThat(m.getPatchSetId()).named(m.toString()).isNotEqualTo(delPsId);
|
||||
}
|
||||
for (Comment c : cd.publishedComments()) {
|
||||
assertThat(c.key.patchSetId).named(c.toString()).isNotEqualTo(delPsId.get());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteDraftPS2() throws Exception {
|
||||
String changeId = createDraftChangeWith2PS();
|
||||
|
||||
ReviewInput rin = new ReviewInput();
|
||||
rin.message = "Change message";
|
||||
CommentInput cin = new CommentInput();
|
||||
cin.line = 1;
|
||||
cin.patchSet = 1;
|
||||
cin.path = PushOneCommit.FILE_NAME;
|
||||
cin.side = Side.REVISION;
|
||||
cin.message = "Inline comment";
|
||||
rin.comments = new HashMap<>();
|
||||
rin.comments.put(cin.path, ImmutableList.of(cin));
|
||||
gApi.changes().id(changeId).revision(1).review(rin);
|
||||
|
||||
ChangeData cd = getChange(changeId);
|
||||
PatchSet.Id delPsId = new PatchSet.Id(cd.getId(), 2);
|
||||
PatchSet ps = cd.patchSet(delPsId);
|
||||
deletePatchSet(changeId, ps);
|
||||
|
||||
cd = getChange(changeId);
|
||||
assertThat(cd.patchSets()).hasSize(1);
|
||||
assertThat(Iterables.getOnlyElement(cd.patchSets()).getId().get()).isEqualTo(1);
|
||||
|
||||
// Other entities based on deleted patch sets are also deleted.
|
||||
for (ChangeMessage m : cd.messages()) {
|
||||
assertThat(m.getPatchSetId()).named(m.toString()).isNotEqualTo(delPsId);
|
||||
}
|
||||
for (Comment c : cd.publishedComments()) {
|
||||
assertThat(c.key.patchSetId).named(c.toString()).isNotEqualTo(delPsId.get());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteCurrentDraftPatchSetWhenPreviousPatchSetDoesNotExist() throws Exception {
|
||||
String changeId = createChange().getChangeId();
|
||||
amendChangeAndMarkPatchSetAsDraft(changeId);
|
||||
amendChangeAndMarkPatchSetAsDraft(changeId);
|
||||
|
||||
deletePatchSet(changeId, 2);
|
||||
deletePatchSet(changeId, 3);
|
||||
|
||||
ChangeData cd = getChange(changeId);
|
||||
assertThat(cd.patchSets()).hasSize(1);
|
||||
assertThat(Iterables.getOnlyElement(cd.patchSets()).getId().get()).isEqualTo(1);
|
||||
assertThat(cd.currentPatchSet().getId().get()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteDraftPatchSetAndPushNewDraftPatchSet() throws Exception {
|
||||
// Create change
|
||||
PushOneCommit.Result r1 = createDraftChange();
|
||||
String changeId = r1.getChangeId();
|
||||
String revPs1 = r1.getChange().currentPatchSet().getRevision().get();
|
||||
|
||||
// Push draft patch set
|
||||
PushOneCommit.Result r2 = amendChangeAndMarkPatchSetAsDraft(changeId);
|
||||
String revPs2 = r2.getChange().currentPatchSet().getRevision().get();
|
||||
|
||||
assertThat(gApi.changes().id(r1.getChange().getId().get()).get().currentRevision)
|
||||
.isEqualTo(revPs2);
|
||||
|
||||
// Remove draft patch set
|
||||
gApi.changes().id(r1.getChange().getId().get()).revision(revPs2).delete();
|
||||
|
||||
assertThat(gApi.changes().id(r1.getChange().getId().get()).get().currentRevision)
|
||||
.isEqualTo(revPs1);
|
||||
|
||||
// Push new draft patch set
|
||||
amendChangeAndMarkPatchSetAsDraft(changeId);
|
||||
String revPs3 = r2.getChange().currentPatchSet().getRevision().get();
|
||||
|
||||
assertThat(gApi.changes().id(r1.getChange().getId().get()).get().currentRevision)
|
||||
.isEqualTo(revPs3);
|
||||
|
||||
// Check that all patch sets have different SHA1s
|
||||
assertThat(revPs1).doesNotMatch(revPs2);
|
||||
assertThat(revPs2).doesNotMatch(revPs3);
|
||||
}
|
||||
|
||||
private Ref getDraftRef(TestAccount account, Change.Id changeId) throws Exception {
|
||||
try (Repository repo = repoManager.openRepository(allUsers)) {
|
||||
return repo.exactRef(RefNames.refsDraftComments(changeId, account.id));
|
||||
}
|
||||
}
|
||||
|
||||
private Ref getMetaRef(Change.Id changeId) throws Exception {
|
||||
try (Repository repo = repoManager.openRepository(project)) {
|
||||
return repo.exactRef(RefNames.changeMetaRef(changeId));
|
||||
}
|
||||
}
|
||||
|
||||
private PatchSet getCurrentPatchSet(String changeId) throws Exception {
|
||||
return getChange(changeId).currentPatchSet();
|
||||
}
|
||||
|
||||
private ChangeData getChange(String changeId) throws Exception {
|
||||
return Iterables.getOnlyElement(queryProvider.get().byKeyPrefix(changeId));
|
||||
}
|
||||
|
||||
private void deletePatchSet(String changeId, PatchSet ps) throws Exception {
|
||||
deletePatchSet(changeId, ps.getId().get());
|
||||
}
|
||||
|
||||
private void deletePatchSet(String changeId, int ps) throws Exception {
|
||||
gApi.changes().id(changeId).revision(ps).delete();
|
||||
}
|
||||
}
|
||||
@@ -1,295 +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.rest.change;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.TruthJUnit.assume;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.gerrit.acceptance.AbstractDaemonTest;
|
||||
import com.google.gerrit.acceptance.PushOneCommit;
|
||||
import com.google.gerrit.acceptance.RestResponse;
|
||||
import com.google.gerrit.acceptance.RestSession;
|
||||
import com.google.gerrit.acceptance.TestProjectInput;
|
||||
import com.google.gerrit.common.data.Permission;
|
||||
import com.google.gerrit.extensions.api.changes.ReviewInput;
|
||||
import com.google.gerrit.extensions.client.ChangeStatus;
|
||||
import com.google.gerrit.extensions.client.ReviewerState;
|
||||
import com.google.gerrit.extensions.common.AccountInfo;
|
||||
import com.google.gerrit.extensions.common.ChangeInfo;
|
||||
import com.google.gerrit.extensions.common.EditInfo;
|
||||
import com.google.gerrit.extensions.common.EditInfoSubject;
|
||||
import com.google.gerrit.extensions.common.LabelInfo;
|
||||
import com.google.gerrit.extensions.restapi.AuthException;
|
||||
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.reviewdb.client.Change;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gerrit.testutil.ConfigSuite;
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
import org.eclipse.jgit.lib.Config;
|
||||
import org.junit.Test;
|
||||
|
||||
public class DraftChangeIT extends AbstractDaemonTest {
|
||||
@ConfigSuite.Config
|
||||
public static Config allowDraftsDisabled() {
|
||||
return allowDraftsDisabledConfig();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void forceCreateAndPublishDraftChangeWhenAllowDraftsDisabled() throws Exception {
|
||||
PushOneCommit.Result result = createDraftChange();
|
||||
result.assertOkStatus();
|
||||
String changeId = result.getChangeId();
|
||||
String triplet = project.get() + "~master~" + changeId;
|
||||
ChangeInfo c = get(triplet);
|
||||
assertThat(c.id).isEqualTo(triplet);
|
||||
assertThat(c.status).isEqualTo(ChangeStatus.DRAFT);
|
||||
assertThat(c.revisions.get(c.currentRevision).draft).isTrue();
|
||||
publishPatchSet(changeId).assertNoContent();
|
||||
assertThat(get(triplet).status).isEqualTo(ChangeStatus.NEW);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteDraftChange() throws Exception {
|
||||
assume().that(isAllowDrafts()).isTrue();
|
||||
PushOneCommit.Result result = createDraftChange();
|
||||
result.assertOkStatus();
|
||||
String changeId = result.getChangeId();
|
||||
String triplet = project.get() + "~master~" + changeId;
|
||||
ChangeInfo c = get(triplet);
|
||||
assertThat(c.id).isEqualTo(triplet);
|
||||
assertThat(c.status).isEqualTo(ChangeStatus.DRAFT);
|
||||
deleteChange(changeId, adminRestSession).assertNoContent();
|
||||
|
||||
exception.expect(ResourceNotFoundException.class);
|
||||
get(triplet);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteDraftChangeOfAnotherUser() throws Exception {
|
||||
assume().that(isAllowDrafts()).isTrue();
|
||||
PushOneCommit.Result changeResult = createDraftChange();
|
||||
changeResult.assertOkStatus();
|
||||
String changeId = changeResult.getChangeId();
|
||||
|
||||
// The user needs to be able to see the draft change (which reviewers can).
|
||||
gApi.changes().id(changeId).addReviewer(user.fullName);
|
||||
|
||||
setApiUser(user);
|
||||
exception.expect(AuthException.class);
|
||||
exception.expectMessage("delete not permitted");
|
||||
gApi.changes().id(changeId).delete();
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestProjectInput(cloneAs = "user")
|
||||
public void deleteDraftChangeWhenDraftsNotAllowedAsNormalUser() throws Exception {
|
||||
assume().that(isAllowDrafts()).isFalse();
|
||||
|
||||
setApiUser(user);
|
||||
// We can't create a draft change while the draft workflow is disabled.
|
||||
// For this reason, we create a normal change and modify the database.
|
||||
PushOneCommit.Result changeResult =
|
||||
pushFactory.create(db, user.getIdent(), testRepo).to("refs/for/master");
|
||||
Change.Id id = changeResult.getChange().getId();
|
||||
markChangeAsDraft(id);
|
||||
setDraftStatusOfPatchSets(id, true);
|
||||
|
||||
String changeId = changeResult.getChangeId();
|
||||
exception.expect(MethodNotAllowedException.class);
|
||||
exception.expectMessage("Draft workflow is disabled");
|
||||
gApi.changes().id(changeId).delete();
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestProjectInput(cloneAs = "user")
|
||||
public void deleteDraftChangeWhenDraftsNotAllowedAsAdmin() throws Exception {
|
||||
assume().that(isAllowDrafts()).isFalse();
|
||||
|
||||
setApiUser(user);
|
||||
// We can't create a draft change while the draft workflow is disabled.
|
||||
// For this reason, we create a normal change and modify the database.
|
||||
PushOneCommit.Result changeResult =
|
||||
pushFactory.create(db, user.getIdent(), testRepo).to("refs/for/master");
|
||||
Change.Id id = changeResult.getChange().getId();
|
||||
markChangeAsDraft(id);
|
||||
setDraftStatusOfPatchSets(id, true);
|
||||
|
||||
String changeId = changeResult.getChangeId();
|
||||
|
||||
// Grant those permissions to admins.
|
||||
grant(project, "refs/*", Permission.VIEW_DRAFTS);
|
||||
grant(project, "refs/*", Permission.DELETE_DRAFTS);
|
||||
|
||||
try {
|
||||
setApiUser(admin);
|
||||
gApi.changes().id(changeId).delete();
|
||||
} finally {
|
||||
removePermission(project, "refs/*", Permission.DELETE_DRAFTS);
|
||||
removePermission(project, "refs/*", Permission.VIEW_DRAFTS);
|
||||
}
|
||||
|
||||
setApiUser(user);
|
||||
assertThat(query(changeId)).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteDraftChangeWithNonDraftPatchSet() throws Exception {
|
||||
assume().that(isAllowDrafts()).isTrue();
|
||||
|
||||
PushOneCommit.Result changeResult = createDraftChange();
|
||||
Change.Id id = changeResult.getChange().getId();
|
||||
setDraftStatusOfPatchSets(id, false);
|
||||
|
||||
String changeId = changeResult.getChangeId();
|
||||
exception.expect(ResourceConflictException.class);
|
||||
exception.expectMessage(
|
||||
String.format("Cannot delete draft change %s: patch set 1 is not a draft", id));
|
||||
gApi.changes().id(changeId).delete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void publishDraftChange() throws Exception {
|
||||
assume().that(isAllowDrafts()).isTrue();
|
||||
PushOneCommit.Result result = createDraftChange();
|
||||
result.assertOkStatus();
|
||||
String changeId = result.getChangeId();
|
||||
String triplet = project.get() + "~master~" + changeId;
|
||||
ChangeInfo c = get(triplet);
|
||||
assertThat(c.id).isEqualTo(triplet);
|
||||
assertThat(c.status).isEqualTo(ChangeStatus.DRAFT);
|
||||
assertThat(c.revisions.get(c.currentRevision).draft).isTrue();
|
||||
publishChange(changeId).assertNoContent();
|
||||
c = get(triplet);
|
||||
assertThat(c.status).isEqualTo(ChangeStatus.NEW);
|
||||
assertThat(c.revisions.get(c.currentRevision).draft).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void publishDraftPatchSet() throws Exception {
|
||||
assume().that(isAllowDrafts()).isTrue();
|
||||
PushOneCommit.Result result = createDraftChange();
|
||||
result.assertOkStatus();
|
||||
String changeId = result.getChangeId();
|
||||
String triplet = project.get() + "~master~" + changeId;
|
||||
ChangeInfo c = get(triplet);
|
||||
assertThat(c.id).isEqualTo(triplet);
|
||||
assertThat(c.status).isEqualTo(ChangeStatus.DRAFT);
|
||||
publishPatchSet(changeId).assertNoContent();
|
||||
assertThat(get(triplet).status).isEqualTo(ChangeStatus.NEW);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createDraftChangeWhenDraftsNotAllowed() throws Exception {
|
||||
assume().that(isAllowDrafts()).isFalse();
|
||||
PushOneCommit.Result r = pushTo("refs/drafts/master");
|
||||
r.assertErrorStatus();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listApprovalsOnDraftChange() throws Exception {
|
||||
assume().that(isAllowDrafts()).isTrue();
|
||||
PushOneCommit.Result result = createDraftChange();
|
||||
result.assertOkStatus();
|
||||
String changeId = result.getChangeId();
|
||||
String triplet = project.get() + "~master~" + changeId;
|
||||
|
||||
gApi.changes().id(triplet).addReviewer(user.fullName);
|
||||
|
||||
ChangeInfo info = get(triplet);
|
||||
LabelInfo label = info.labels.get("Code-Review");
|
||||
assertThat(label.all).hasSize(1);
|
||||
assertThat(label.all.get(0)._accountId).isEqualTo(user.id.get());
|
||||
assertThat(label.all.get(0).value).isEqualTo(0);
|
||||
|
||||
Collection<AccountInfo> ccs = info.reviewers.get(ReviewerState.REVIEWER);
|
||||
assertThat(ccs).hasSize(1);
|
||||
assertThat(ccs.iterator().next()._accountId).isEqualTo(user.id.get());
|
||||
|
||||
setApiUser(user);
|
||||
gApi.changes().id(triplet).current().review(ReviewInput.recommend());
|
||||
setApiUser(admin);
|
||||
|
||||
label = get(triplet).labels.get("Code-Review");
|
||||
assertThat(label.all).hasSize(1);
|
||||
assertThat(label.all.get(0)._accountId).isEqualTo(user.id.get());
|
||||
assertThat(label.all.get(0).value).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pushWithDraftOptionGetsPrivateChange() throws Exception {
|
||||
assume().that(isAllowDrafts()).isTrue();
|
||||
PushOneCommit.Result result = createChange("refs/drafts/master");
|
||||
String changeId = result.getChangeId();
|
||||
ChangeInfo changeInfo = gApi.changes().id(changeId).get();
|
||||
|
||||
assertThat(changeInfo.status).isEqualTo(ChangeStatus.NEW);
|
||||
assertThat(changeInfo.isPrivate).isEqualTo(true);
|
||||
assertThat(changeInfo.revisions).hasSize(1);
|
||||
assertThat(Iterables.getOnlyElement(changeInfo.revisions.values()).draft).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pushWithDraftOptionToExistingNewChangeGetsChangeEdit() throws Exception {
|
||||
assume().that(isAllowDrafts()).isTrue();
|
||||
pushWithDraftOptionToExistingChangeGetsChangeEdit(createChange().getChangeId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pushWithDraftOptionToExistingDraftChangeGetsChangeEdit() throws Exception {
|
||||
assume().that(isAllowDrafts()).isTrue();
|
||||
pushWithDraftOptionToExistingChangeGetsChangeEdit(createDraftChange().getChangeId());
|
||||
}
|
||||
|
||||
private void pushWithDraftOptionToExistingChangeGetsChangeEdit(String changeId) throws Exception {
|
||||
Optional<EditInfo> edit = getEdit(changeId);
|
||||
EditInfoSubject.assertThat(edit).isAbsent();
|
||||
|
||||
ChangeInfo changeInfo = gApi.changes().id(changeId).get();
|
||||
ChangeStatus originalChangeStatus = changeInfo.status;
|
||||
Boolean originalPatchSetStatus = Iterables.getOnlyElement(changeInfo.revisions.values()).draft;
|
||||
|
||||
PushOneCommit.Result result = amendChange(changeId, "refs/drafts/master");
|
||||
result.assertOkStatus();
|
||||
|
||||
changeInfo = gApi.changes().id(changeId).get();
|
||||
assertThat(changeInfo.status).isEqualTo(originalChangeStatus);
|
||||
assertThat(changeInfo.isPrivate).isNull();
|
||||
assertThat(changeInfo.revisions).hasSize(1);
|
||||
assertThat(Iterables.getOnlyElement(changeInfo.revisions.values()).draft)
|
||||
.isEqualTo(originalPatchSetStatus);
|
||||
|
||||
edit = getEdit(changeId);
|
||||
EditInfoSubject.assertThat(edit).isPresent();
|
||||
}
|
||||
|
||||
private static RestResponse deleteChange(String changeId, RestSession s) throws Exception {
|
||||
return s.delete("/changes/" + changeId);
|
||||
}
|
||||
|
||||
private RestResponse publishChange(String changeId) throws Exception {
|
||||
return adminRestSession.post("/changes/" + changeId + "/publish");
|
||||
}
|
||||
|
||||
private RestResponse publishPatchSet(String changeId) throws Exception {
|
||||
PatchSet patchSet =
|
||||
Iterables.getOnlyElement(queryProvider.get().byKeyPrefix(changeId)).currentPatchSet();
|
||||
return adminRestSession.post(
|
||||
"/changes/" + changeId + "/revisions/" + patchSet.getRevision().get() + "/publish");
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@ 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;
|
||||
@@ -509,30 +508,6 @@ public class SubmitByMergeIfNecessaryIT extends AbstractSubmitByMerge {
|
||||
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");
|
||||
|
||||
@@ -25,15 +25,11 @@ import com.google.gerrit.extensions.api.changes.SubmittedTogetherInfo;
|
||||
import com.google.gerrit.extensions.client.ChangeStatus;
|
||||
import com.google.gerrit.extensions.client.ListChangesOption;
|
||||
import com.google.gerrit.extensions.client.SubmitType;
|
||||
import com.google.gerrit.extensions.common.ChangeInfo;
|
||||
import com.google.gerrit.extensions.common.FileInfo;
|
||||
import com.google.gerrit.extensions.common.RevisionInfo;
|
||||
import com.google.gerrit.extensions.restapi.AuthException;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.testutil.ConfigSuite;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import org.eclipse.jgit.junit.TestRepository;
|
||||
import org.eclipse.jgit.lib.Config;
|
||||
import org.eclipse.jgit.revwalk.RevCommit;
|
||||
@@ -155,101 +151,6 @@ public class SubmittedTogetherIT extends AbstractDaemonTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hiddenDraftInTopic() throws Exception {
|
||||
String id1 = createChange("subject", "a", "1", "topic").getChangeId();
|
||||
createDraftChange("topic");
|
||||
|
||||
setApiUser(user);
|
||||
SubmittedTogetherInfo result =
|
||||
gApi.changes().id(id1).submittedTogether(EnumSet.of(NON_VISIBLE_CHANGES));
|
||||
|
||||
if (isSubmitWholeTopicEnabled()) {
|
||||
assertThat(result.changes).hasSize(1);
|
||||
assertThat(result.changes.get(0).changeId).isEqualTo(id1);
|
||||
assertThat(result.nonVisibleChanges).isEqualTo(1);
|
||||
} else {
|
||||
assertThat(result.changes).isEmpty();
|
||||
assertThat(result.nonVisibleChanges).isEqualTo(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hiddenDraftInTopicOldApi() throws Exception {
|
||||
String id1 = createChange("subject", "a", "1", "topic").getChangeId();
|
||||
createDraftChange("topic");
|
||||
|
||||
setApiUser(user);
|
||||
if (isSubmitWholeTopicEnabled()) {
|
||||
exception.expect(AuthException.class);
|
||||
exception.expectMessage("change would be submitted with a change that you cannot see");
|
||||
gApi.changes().id(id1).submittedTogether();
|
||||
} else {
|
||||
List<ChangeInfo> result = gApi.changes().id(id1).submittedTogether();
|
||||
assertThat(result).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void draftPatchSetInTopic() throws Exception {
|
||||
RevCommit initialHead = getRemoteHead();
|
||||
RevCommit a1 = commitBuilder().add("a", "1").message("change 1").create();
|
||||
pushHead(testRepo, "refs/for/master/" + name("topic"), false);
|
||||
String id1 = getChangeId(a1);
|
||||
|
||||
testRepo.reset(initialHead);
|
||||
String parentId = createChange().getChangeId();
|
||||
|
||||
// TODO(jrn): use insertChangeId(id1) once jgit TestRepository accepts the leading "I".
|
||||
commitBuilder()
|
||||
.insertChangeId(id1.substring(1))
|
||||
.add("a", "2")
|
||||
.message("draft patch set on change 1")
|
||||
.create();
|
||||
pushHead(testRepo, "refs/for/master/" + name("topic"), false);
|
||||
setCurrentPatchSetAsDraft(new Change.Id(gApi.changes().id(id1).get()._number));
|
||||
|
||||
testRepo.reset(initialHead);
|
||||
RevCommit b = commitBuilder().message("change with same topic").create();
|
||||
pushHead(testRepo, "refs/for/master/" + name("topic"), false);
|
||||
String id2 = getChangeId(b);
|
||||
|
||||
if (isSubmitWholeTopicEnabled()) {
|
||||
setApiUser(user);
|
||||
assertSubmittedTogether(id2, id2, id1);
|
||||
setApiUser(admin);
|
||||
assertSubmittedTogether(id2, id2, id1, parentId);
|
||||
} else {
|
||||
setApiUser(user);
|
||||
assertSubmittedTogether(id2);
|
||||
setApiUser(admin);
|
||||
assertSubmittedTogether(id2);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void doNotRevealVisibleAncestorOfHiddenDraft() throws Exception {
|
||||
RevCommit initialHead = getRemoteHead();
|
||||
createChange().getChangeId();
|
||||
|
||||
createDraftChange("topic");
|
||||
|
||||
testRepo.reset(initialHead);
|
||||
String id = createChange("subject", "b", "1", "topic").getChangeId();
|
||||
|
||||
setApiUser(user);
|
||||
SubmittedTogetherInfo result =
|
||||
gApi.changes().id(id).submittedTogether(EnumSet.of(NON_VISIBLE_CHANGES));
|
||||
if (isSubmitWholeTopicEnabled()) {
|
||||
assertThat(result.changes).hasSize(1);
|
||||
assertThat(result.changes.get(0).changeId).isEqualTo(id);
|
||||
assertThat(result.nonVisibleChanges).isEqualTo(2);
|
||||
} else {
|
||||
assertThat(result.changes).isEmpty();
|
||||
assertThat(result.nonVisibleChanges).isEqualTo(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void topicChaining() throws Exception {
|
||||
RevCommit initialHead = getRemoteHead();
|
||||
|
||||
@@ -42,7 +42,6 @@ import com.google.gerrit.extensions.api.changes.ReviewInput;
|
||||
import com.google.gerrit.extensions.api.changes.ReviewInput.CommentInput;
|
||||
import com.google.gerrit.extensions.api.changes.ReviewInput.DraftHandling;
|
||||
import com.google.gerrit.extensions.client.Side;
|
||||
import com.google.gerrit.extensions.common.ChangeInfo;
|
||||
import com.google.gerrit.extensions.common.CommentInfo;
|
||||
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
||||
import com.google.gerrit.extensions.restapi.RestApiException;
|
||||
@@ -816,20 +815,6 @@ public class ChangeRebuilderIT extends AbstractDaemonTest {
|
||||
assertThat(nc.getOriginalSubject()).isEqualTo(orig);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteDraftPS1WithNoOtherEntities() throws Exception {
|
||||
String r = createDraftChangeWith2PS();
|
||||
gApi.changes().id(r).revision(1).delete();
|
||||
ChangeInfo changeInfo = get(r);
|
||||
|
||||
Change.Id id = new Change.Id(changeInfo._number);
|
||||
checker.rebuildAndCheckChanges(id);
|
||||
|
||||
setNotesMigration(true, true);
|
||||
ChangeNotes notes = notesFactory.create(db, project, id);
|
||||
assertThat(notes.getPatchSets().keySet()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ignorePatchLineCommentsOnPatchSet0() throws Exception {
|
||||
PushOneCommit.Result r = createChange();
|
||||
|
||||
@@ -16,7 +16,6 @@ package com.google.gerrit.acceptance.ssh;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.Truth.assertWithMessage;
|
||||
import static com.google.gerrit.acceptance.GitUtil.initSsh;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.gerrit.acceptance.AbstractDaemonTest;
|
||||
@@ -290,27 +289,6 @@ public class QueryIT extends AbstractDaemonTest {
|
||||
assertThat(changes.get(0).submitRecords.size()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryWithNonVisibleCurrentPatchSet() throws Exception {
|
||||
String changeId = createChange().getChangeId();
|
||||
amendChangeAndMarkPatchSetAsDraft(changeId);
|
||||
String query = "--current-patch-set --patch-sets " + changeId;
|
||||
List<ChangeAttribute> changes = executeSuccessfulQuery(query);
|
||||
assertThat(changes.size()).isEqualTo(1);
|
||||
assertThat(changes.get(0).patchSets).isNotNull();
|
||||
assertThat(changes.get(0).patchSets).hasSize(2);
|
||||
assertThat(changes.get(0).currentPatchSet).isNotNull();
|
||||
|
||||
SshSession userSession = new SshSession(server, user);
|
||||
initSsh(user);
|
||||
userSession.open();
|
||||
changes = executeSuccessfulQuery(query, userSession);
|
||||
assertThat(changes.size()).isEqualTo(1);
|
||||
assertThat(changes.get(0).patchSets).hasSize(1);
|
||||
assertThat(changes.get(0).currentPatchSet).isNull();
|
||||
userSession.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allChangeOptionsAreServedWithoutExceptions() throws Exception {
|
||||
PushOneCommit.Result r = createChange();
|
||||
|
||||
Reference in New Issue
Block a user