InlineEdit: Add DELETE /changes/<id>/edit REST endpoint
Add REST endpoint to delete a file in change edit or change edit itself.
Change-Id: Ieeb15d0a91ab678f53db367bacd231314c1cf0be
diff --git a/Documentation/rest-api-changes.txt b/Documentation/rest-api-changes.txt
index ac72ef8..5926fe6 100644
--- a/Documentation/rest-api-changes.txt
+++ b/Documentation/rest-api-changes.txt
@@ -1338,6 +1338,26 @@
HTTP/1.1 204 No Content
----
+[[delete-edit]]
+=== Delete Change Edit
+--
+'DELETE /changes/link:#change-id[\{change-id\}]/edit'
+--
+
+Deletes change edit.
+
+.Request
+----
+ DELETE /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/edit HTTP/1.0
+----
+
+As response "`204 No Content`" is returned.
+
+.Response
+----
+ HTTP/1.1 204 No Content
+----
+
[[reviewer-endpoints]]
== Reviewer Endpoints
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/edit/ChangeEditIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/edit/ChangeEditIT.java
index a9a88af..e1040e3 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/edit/ChangeEditIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/edit/ChangeEditIT.java
@@ -17,6 +17,7 @@
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.apache.http.HttpStatus.SC_BAD_REQUEST;
import static org.apache.http.HttpStatus.SC_NO_CONTENT;
import static org.apache.http.HttpStatus.SC_OK;
import static org.junit.Assert.assertArrayEquals;
@@ -189,6 +190,24 @@
}
@Test
+ public void deleteEditRest() throws Exception {
+ assertEquals(RefUpdate.Result.NEW,
+ modifier.createEdit(
+ change,
+ ps));
+ assertEquals(RefUpdate.Result.FORCED,
+ modifier.modifyFile(
+ editUtil.byChange(change).get(),
+ FILE_NAME,
+ CONTENT_NEW));
+ Optional<ChangeEdit> edit = editUtil.byChange(change);
+ RestResponse r = session.delete(urlEdit());
+ assertEquals(SC_NO_CONTENT, r.getStatusCode());
+ edit = editUtil.byChange(change);
+ assertFalse(edit.isPresent());
+ }
+
+ @Test
public void rebaseEdit() throws Exception {
assertEquals(RefUpdate.Result.NEW,
modifier.createEdit(
@@ -317,6 +336,25 @@
}
@Test
+ public void createEditByDeletingExistingFileRest() throws Exception {
+ RestResponse r = session.delete(urlEditFile());
+ assertEquals(SC_NO_CONTENT, r.getStatusCode());
+ Optional<ChangeEdit> edit = editUtil.byChange(change);
+ try {
+ fileUtil.getContent(edit.get().getChange().getProject(),
+ edit.get().getRevision().get(), FILE_NAME);
+ fail("ResourceNotFoundException expected");
+ } catch (ResourceNotFoundException rnfe) {
+ }
+ }
+
+ @Test
+ public void deletingNonExistingEditRest() throws Exception {
+ RestResponse r = session.delete(urlEdit());
+ assertEquals(SC_BAD_REQUEST, r.getStatusCode());
+ }
+
+ @Test
public void deleteExistingFileRest() throws Exception {
assertEquals(RefUpdate.Result.NEW,
modifier.createEdit(
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeEdits.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeEdits.java
index fd91476..ef0b8ea 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeEdits.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeEdits.java
@@ -21,8 +21,10 @@
import com.google.gerrit.extensions.common.EditInfo;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.restapi.AcceptsCreate;
+import com.google.gerrit.extensions.restapi.AcceptsDelete;
import com.google.gerrit.extensions.restapi.AcceptsPost;
import com.google.gerrit.extensions.restapi.AuthException;
+import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.ChildCollection;
import com.google.gerrit.extensions.restapi.DefaultInput;
import com.google.gerrit.extensions.restapi.IdString;
@@ -54,9 +56,11 @@
public class ChangeEdits implements
ChildCollection<ChangeResource, ChangeEditResource>,
AcceptsCreate<ChangeResource>,
- AcceptsPost<ChangeResource> {
+ AcceptsPost<ChangeResource>,
+ AcceptsDelete<ChangeResource> {
private final DynamicMap<RestView<ChangeEditResource>> views;
private final Create.Factory createFactory;
+ private final DeleteEdit.Factory deleteEditFactory;
private final Detail detail;
private final ChangeEditUtil editUtil;
private final Post post;
@@ -66,12 +70,14 @@
Create.Factory createFactory,
Detail detail,
ChangeEditUtil editUtil,
- Post post) {
+ Post post,
+ DeleteEdit.Factory deleteEditFactory) {
this.views = views;
this.createFactory = createFactory;
this.detail = detail;
this.editUtil = editUtil;
this.post = post;
+ this.deleteEditFactory = deleteEditFactory;
}
@Override
@@ -115,6 +121,14 @@
* change edit wasn't created yet. Change edit is created and PUT
* handler is called.
*/
+ @SuppressWarnings("unchecked")
+ @Override
+ public DeleteEdit delete(ChangeResource parent, IdString id)
+ throws RestApiException {
+ return deleteEditFactory.create(parent.getChange(),
+ id != null ? id.get() : null);
+ }
+
static class Create implements
RestModifyView<ChangeResource, Put.Input> {
@@ -171,6 +185,57 @@
}
}
+ static class DeleteEdit implements
+ RestModifyView<ChangeResource, DeleteEdit.Input> {
+ public static class Input {
+ }
+
+ interface Factory {
+ DeleteEdit create(Change change, String path);
+ }
+
+ private final ChangeEditUtil editUtil;
+ private final ChangeEditModifier editModifier;
+ private final Provider<ReviewDb> db;
+ private final String path;
+
+ @Inject
+ DeleteEdit(ChangeEditUtil editUtil,
+ ChangeEditModifier editModifier,
+ Provider<ReviewDb> db,
+ @Assisted @Nullable String path) {
+ this.editUtil = editUtil;
+ this.editModifier = editModifier;
+ this.db = db;
+ this.path = path;
+ }
+
+ @Override
+ public Response<?> apply(ChangeResource rsrc, DeleteEdit.Input in)
+ throws IOException, AuthException, ResourceConflictException,
+ OrmException, InvalidChangeOperationException, BadRequestException {
+ Optional<ChangeEdit> edit = editUtil.byChange(rsrc.getChange());
+ if (edit.isPresent() && path == null) {
+ // Edit is wiped out
+ editUtil.delete(edit.get());
+ } else if (!edit.isPresent() && path != null) {
+ // Edit is created on top of current patch set by deleting path.
+ // Even if the latest patch set changed since the user triggered
+ // the operation, deleting the whole file is probably still what
+ // they intended.
+ editModifier.createEdit(rsrc.getChange(), db.get().patchSets().get(
+ rsrc.getChange().currentPatchSetId()));
+ edit = editUtil.byChange(rsrc.getChange());
+ editModifier.deleteFile(edit.get(), path);
+ } else {
+ // Bad request
+ throw new BadRequestException(
+ "change edit doesn't exist and no path was provided");
+ }
+ return Response.none();
+ }
+ }
+
@Singleton
static class Detail implements RestReadView<ChangeResource> {
private final ChangeEditUtil editUtil;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Module.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Module.java
index dd63f5d..a916430 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Module.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Module.java
@@ -117,6 +117,7 @@
factory(ChangeInserter.Factory.class);
factory(PatchSetInserter.Factory.class);
factory(ChangeEdits.Create.Factory.class);
+ factory(ChangeEdits.DeleteEdit.Factory.class);
}
});
}