diff --git a/Documentation/rest-api-changes.txt b/Documentation/rest-api-changes.txt index 8c3d91086a..c499eaade9 100644 --- a/Documentation/rest-api-changes.txt +++ b/Documentation/rest-api-changes.txt @@ -1217,6 +1217,36 @@ content isn't provided, it is wiped out for that file. As response HTTP/1.1 204 No Content ---- +[[post-edit]] +=== Restore file content in Change Edit +-- +'POST /changes/link:#change-id[\{change-id\}]/edit +-- + +Creates empty change edit or restores file content in change edit. The +request body needs to include a link:#change-edit-input[ChangeEditInput] +entity when a file within change edit should be restored. + +.Request +---- + POST /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/edit HTTP/1.0 + Content-Type: application/json;charset=UTF-8 + + { + "path": "foo", + "restore": true + } +---- + +When change edit doesn't exist for this change yet it is created. When path +and restore flag are provided in request body, this file is restored. As +response "`204 No Content`" is returned. + +.Response +---- + HTTP/1.1 204 No Content +---- + [[reviewer-endpoints]] == Reviewer Endpoints @@ -3677,6 +3707,17 @@ The `EditInfo` entity contains information about a change edit. link:#commit-info[CommitInfo] entity. |=========================== +[[restore-path-input]] +=== RestorePathInput +The `RestorePathInput` entity contains information for restoring a +path within change edit. + +[options="header",width="50%",cols="1,^1,5"] +|=========================== +|Field Name ||Description +|`restore_path`|optional|Path to file to restore. +|=========================== + GERRIT ------ Part of link:index.html[Gerrit Code Review] 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 5b1c80150f..8814a9eb6e 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 @@ -40,6 +40,7 @@ import com.google.gerrit.reviewdb.client.PatchSet; import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.server.IdentifiedUser; import com.google.gerrit.server.change.ChangeEdits.Put; +import com.google.gerrit.server.change.ChangeEdits.Post; import com.google.gerrit.server.change.FileContentUtil; import com.google.gerrit.server.edit.ChangeEdit; import com.google.gerrit.server.edit.ChangeEditModifier; @@ -315,6 +316,18 @@ public class ChangeEditIT extends AbstractDaemonTest { edit.get().getRevision().get(), FILE_NAME))); } + @Test + public void restoreDeletedFileInPatchSetRest() throws Exception { + Post.Input in = new Post.Input(); + in.restorePath = FILE_NAME; + assertEquals(SC_NO_CONTENT, session.post(urlEdit2(), + in).getStatusCode()); + Optional edit = editUtil.byChange(change2); + assertArrayEquals(CONTENT_OLD, + toBytes(fileUtil.getContent(edit.get().getChange().getProject(), + edit.get().getRevision().get(), FILE_NAME))); + } + @Test public void amendExistingFile() throws Exception { assertEquals(RefUpdate.Result.NEW, @@ -390,6 +403,15 @@ public class ChangeEditIT extends AbstractDaemonTest { edit.get().getRevision().get(), FILE_NAME))); } + @Test + public void createEmptyEditRest() throws Exception { + assertEquals(SC_NO_CONTENT, session.post(urlEdit()).getStatusCode()); + Optional edit = editUtil.byChange(change); + assertArrayEquals(CONTENT_OLD, + toBytes(fileUtil.getContent(edit.get().getChange().getProject(), + edit.get().getRevision().get(), FILE_NAME))); + } + @Test public void addNewFile() throws Exception { assertEquals(RefUpdate.Result.NEW, @@ -495,6 +517,12 @@ public class ChangeEditIT extends AbstractDaemonTest { + "/edit"; } + private String urlEdit2() { + return "/changes/" + + change2.getChangeId() + + "/edit/"; + } + private String urlEditFile() { return urlEdit() + "/" 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 9a1979f209..c8439e8437 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,7 +21,9 @@ import com.google.gerrit.common.Nullable; 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.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; @@ -52,21 +54,25 @@ import java.io.IOException; @Singleton public class ChangeEdits implements ChildCollection, - AcceptsCreate { + AcceptsCreate, + AcceptsPost { private final DynamicMap> views; private final Create.Factory createFactory; private final Detail detail; private final ChangeEditUtil editUtil; + private final Post post; @Inject ChangeEdits(DynamicMap> views, Create.Factory createFactory, Detail detail, - ChangeEditUtil editUtil) { + ChangeEditUtil editUtil, + Post post) { this.views = views; this.createFactory = createFactory; this.detail = detail; this.editUtil = editUtil; + this.post = post; } @Override @@ -97,6 +103,13 @@ public class ChangeEdits implements return createFactory.create(parent.getChange(), id.get()); } + + @SuppressWarnings("unchecked") + @Override + public Post post(ChangeResource parent) throws RestApiException { + return post; + } + /** * Create handler that is activated when collection element is accessed * but doesn't exist, e. g. PUT request with a path was called but @@ -183,6 +196,59 @@ public class ChangeEdits implements } } + /** + * Post to edit collection resource. Two different operations are + * supported: + *
    + *
  • Create non existing change edit
  • + *
  • Restore path in existing change edit
  • + *
+ * The combination of two operations in one request is supported. + */ + @Singleton + public static class Post implements + RestModifyView { + public static class Input { + public String restorePath; + } + + private final Provider db; + private final ChangeEditUtil editUtil; + private final ChangeEditModifier editModifier; + + @Inject + Post(Provider db, + ChangeEditUtil editUtil, + ChangeEditModifier editModifier) { + this.db = db; + this.editUtil = editUtil; + this.editModifier = editModifier; + } + + @Override + public Response apply(ChangeResource resource, Post.Input input) + throws AuthException, InvalidChangeOperationException, IOException, + ResourceConflictException, OrmException { + Optional edit = editUtil.byChange(resource.getChange()); + if (!edit.isPresent()) { + edit = createEdit(resource.getChange()); + } + + if (input != null && !Strings.isNullOrEmpty(input.restorePath)) { + editModifier.restoreFile(edit.get(), input.restorePath); + } + return Response.none(); + } + + private Optional createEdit(Change change) + throws AuthException, IOException, ResourceConflictException, + OrmException, InvalidChangeOperationException { + editModifier.createEdit(change, + db.get().patchSets().get(change.currentPatchSetId())); + return editUtil.byChange(change); + } + } + /** * Put handler that is activated when PUT request is called on * collection element.