Line data Source code
1 : // Copyright (C) 2012 The Android Open Source Project 2 : // 3 : // Licensed under the Apache License, Version 2.0 (the "License"); 4 : // you may not use this file except in compliance with the License. 5 : // You may obtain a copy of the License at 6 : // 7 : // http://www.apache.org/licenses/LICENSE-2.0 8 : // 9 : // Unless required by applicable law or agreed to in writing, software 10 : // distributed under the License is distributed on an "AS IS" BASIS, 11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : // See the License for the specific language governing permissions and 13 : // limitations under the License. 14 : 15 : package com.google.gerrit.server.restapi.change; 16 : 17 : import com.google.gerrit.entities.Change; 18 : import com.google.gerrit.extensions.api.changes.AbandonInput; 19 : import com.google.gerrit.extensions.api.changes.NotifyHandling; 20 : import com.google.gerrit.extensions.common.ChangeInfo; 21 : import com.google.gerrit.extensions.restapi.Response; 22 : import com.google.gerrit.extensions.restapi.RestApiException; 23 : import com.google.gerrit.extensions.restapi.RestModifyView; 24 : import com.google.gerrit.extensions.webui.UiAction; 25 : import com.google.gerrit.server.CurrentUser; 26 : import com.google.gerrit.server.PatchSetUtil; 27 : import com.google.gerrit.server.account.AccountState; 28 : import com.google.gerrit.server.change.AbandonOp; 29 : import com.google.gerrit.server.change.ChangeJson; 30 : import com.google.gerrit.server.change.ChangeResource; 31 : import com.google.gerrit.server.change.NotifyResolver; 32 : import com.google.gerrit.server.notedb.ChangeNotes; 33 : import com.google.gerrit.server.notedb.StoreSubmitRequirementsOp; 34 : import com.google.gerrit.server.permissions.ChangePermission; 35 : import com.google.gerrit.server.permissions.PermissionBackendException; 36 : import com.google.gerrit.server.query.change.ChangeData; 37 : import com.google.gerrit.server.update.BatchUpdate; 38 : import com.google.gerrit.server.update.UpdateException; 39 : import com.google.gerrit.server.util.time.TimeUtil; 40 : import com.google.inject.Inject; 41 : import com.google.inject.Singleton; 42 : import java.io.IOException; 43 : import org.eclipse.jgit.errors.ConfigInvalidException; 44 : 45 : @Singleton 46 : public class Abandon 47 : implements RestModifyView<ChangeResource, AbandonInput>, UiAction<ChangeResource> { 48 : private final ChangeData.Factory changeDataFactory; 49 : private final BatchUpdate.Factory updateFactory; 50 : private final ChangeJson.Factory json; 51 : private final AbandonOp.Factory abandonOpFactory; 52 : private final NotifyResolver notifyResolver; 53 : private final PatchSetUtil patchSetUtil; 54 : private final StoreSubmitRequirementsOp.Factory storeSubmitRequirementsOpFactory; 55 : 56 : @Inject 57 : Abandon( 58 : ChangeData.Factory changeDataFactory, 59 : BatchUpdate.Factory updateFactory, 60 : ChangeJson.Factory json, 61 : AbandonOp.Factory abandonOpFactory, 62 : NotifyResolver notifyResolver, 63 : PatchSetUtil patchSetUtil, 64 145 : StoreSubmitRequirementsOp.Factory storeSubmitRequirementsOpFactory) { 65 145 : this.changeDataFactory = changeDataFactory; 66 145 : this.updateFactory = updateFactory; 67 145 : this.json = json; 68 145 : this.abandonOpFactory = abandonOpFactory; 69 145 : this.notifyResolver = notifyResolver; 70 145 : this.patchSetUtil = patchSetUtil; 71 145 : this.storeSubmitRequirementsOpFactory = storeSubmitRequirementsOpFactory; 72 145 : } 73 : 74 : @Override 75 : public Response<ChangeInfo> apply(ChangeResource rsrc, AbandonInput input) 76 : throws RestApiException, UpdateException, PermissionBackendException, IOException, 77 : ConfigInvalidException { 78 : // Not allowed to abandon if the current patch set is locked. 79 20 : patchSetUtil.checkPatchSetNotLocked(rsrc.getNotes()); 80 : 81 20 : rsrc.permissions().check(ChangePermission.ABANDON); 82 : 83 20 : NotifyHandling notify = input.notify == null ? defaultNotify(rsrc.getChange()) : input.notify; 84 20 : Change change = 85 20 : abandon( 86 : updateFactory, 87 20 : rsrc.getNotes(), 88 20 : rsrc.getUser(), 89 : input.message, 90 20 : notifyResolver.resolve(notify, input.notifyDetails)); 91 20 : return Response.ok(json.noOptions().format(change)); 92 : } 93 : 94 : private NotifyHandling defaultNotify(Change change) { 95 20 : return change.hasReviewStarted() ? NotifyHandling.ALL : NotifyHandling.OWNER; 96 : } 97 : 98 : public Change abandon(BatchUpdate.Factory updateFactory, ChangeNotes notes, CurrentUser user) 99 : throws RestApiException, UpdateException { 100 0 : return abandon( 101 : updateFactory, 102 : notes, 103 : user, 104 : "", 105 0 : NotifyResolver.Result.create(defaultNotify(notes.getChange()))); 106 : } 107 : 108 : public Change abandon( 109 : BatchUpdate.Factory updateFactory, ChangeNotes notes, CurrentUser user, String msgTxt) 110 : throws RestApiException, UpdateException { 111 0 : return abandon( 112 : updateFactory, 113 : notes, 114 : user, 115 : msgTxt, 116 0 : NotifyResolver.Result.create(defaultNotify(notes.getChange()))); 117 : } 118 : 119 : public Change abandon( 120 : BatchUpdate.Factory updateFactory, 121 : ChangeNotes notes, 122 : CurrentUser user, 123 : String msgTxt, 124 : NotifyResolver.Result notify) 125 : throws RestApiException, UpdateException { 126 20 : AccountState accountState = user.isIdentifiedUser() ? user.asIdentifiedUser().state() : null; 127 20 : AbandonOp op = abandonOpFactory.create(accountState, msgTxt); 128 20 : ChangeData changeData = changeDataFactory.create(notes.getProjectName(), notes.getChangeId()); 129 20 : try (BatchUpdate u = updateFactory.create(notes.getProjectName(), user, TimeUtil.now())) { 130 20 : u.setNotify(notify); 131 20 : u.addOp(notes.getChangeId(), op); 132 20 : u.addOp( 133 20 : notes.getChangeId(), 134 20 : storeSubmitRequirementsOpFactory.create( 135 20 : changeData.submitRequirements().values(), changeData)); 136 20 : u.execute(); 137 : } 138 20 : return op.getChange(); 139 : } 140 : 141 : @Override 142 : public UiAction.Description getDescription(ChangeResource rsrc) throws IOException { 143 57 : UiAction.Description description = 144 : new UiAction.Description() 145 57 : .setLabel("Abandon") 146 57 : .setTitle("Abandon the change") 147 57 : .setVisible(false); 148 : 149 57 : Change change = rsrc.getChange(); 150 57 : if (!change.isNew()) { 151 25 : return description; 152 : } 153 52 : if (patchSetUtil.isPatchSetLocked(rsrc.getNotes())) { 154 0 : return description; 155 : } 156 52 : return description.setVisible(rsrc.permissions().testOrFalse(ChangePermission.ABANDON)); 157 : } 158 : }