InlineEdit: Allow to list files in change edit

Add --list and --base option to GET edit REST endpoint to list files
in change edit:

  GET /changes/<id>/edit?list

Change-Id: Idfb6278c67750c09b41653dda050b560d05695f8
This commit is contained in:
David Ostrovsky
2014-08-01 09:23:28 +02:00
parent 8e75f5070e
commit 5d98e34ab6
7 changed files with 92 additions and 18 deletions

View File

@@ -1162,6 +1162,9 @@ As response an link:#edit-info[EditInfo] entity is returned that
describes the change edit, or "`204 No Content`" when change edit doesn't
exist for this change. Change edits are stored on special branches and there
can be max one edit per user per change. Edits aren't tracked in the database.
When request parameter `list` is provided the response also includes the file
list. When `base` request parameter is provided the file list is computed
against this base revision.
.Response
----
@@ -3816,6 +3819,9 @@ The `EditInfo` entity contains information about a change edit.
|Field Name ||Description
|`commit` ||The commit of change edit as
link:#commit-info[CommitInfo] entity.
|`files` |optional|
The files of the change edit as a map that maps the file names to
link:#file-info[FileInfo] entities.
|===========================
[[restore-path-input]]

View File

@@ -28,6 +28,7 @@ import static org.junit.Assert.fail;
import com.google.common.base.Optional;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.AcceptanceTestRequestScope;
import com.google.gerrit.acceptance.PushOneCommit;
@@ -66,6 +67,7 @@ import org.junit.Test;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
public class ChangeEditIT extends AbstractDaemonTest {
@@ -304,7 +306,7 @@ public class ChangeEditIT extends AbstractDaemonTest {
FILE_NAME,
CONTENT_NEW));
edit = editUtil.byChange(change);
EditInfo info = toEditInfo();
EditInfo info = toEditInfo(false);
assertEquals(edit.get().getRevision().get(), info.commit.commit);
assertEquals(1, info.commit.parents.size());
@@ -315,6 +317,26 @@ public class ChangeEditIT extends AbstractDaemonTest {
assertEquals(SC_NO_CONTENT, r.getStatusCode());
}
@Test
public void retrieveFilesInEdit() throws Exception {
assertEquals(RefUpdate.Result.NEW,
modifier.createEdit(
change,
ps));
Optional<ChangeEdit> edit = editUtil.byChange(change);
assertEquals(RefUpdate.Result.FORCED,
modifier.modifyFile(
edit.get(),
FILE_NAME,
CONTENT_NEW));
EditInfo info = toEditInfo(true);
assertEquals(2, info.files.size());
List<String> l = Lists.newArrayList(info.files.keySet());
assertEquals("/COMMIT_MSG", l.get(0));
assertEquals("foo", l.get(1));
}
@Test
public void deleteExistingFile() throws Exception {
assertEquals(RefUpdate.Result.NEW,
@@ -675,6 +697,11 @@ public class ChangeEditIT extends AbstractDaemonTest {
+ FILE_NAME;
}
private String urlGetFiles() {
return urlEdit()
+ "?list";
}
private String urlPublish() {
return "/changes/"
+ change.getChangeId()
@@ -687,8 +714,8 @@ public class ChangeEditIT extends AbstractDaemonTest {
+ "/rebase_edit";
}
private EditInfo toEditInfo() throws IOException {
RestResponse r = session.get(urlEdit());
private EditInfo toEditInfo(boolean files) throws IOException {
RestResponse r = session.get(files ? urlGetFiles() : urlEdit());
assertEquals(SC_OK, r.getStatusCode());
return newGson().fromJson(r.getReader(), EditInfo.class);
}

View File

@@ -14,6 +14,9 @@
package com.google.gerrit.extensions.common;
import java.util.Map;
public class EditInfo {
public CommitInfo commit;
public Map<String, FileInfo> files;
}

View File

@@ -208,6 +208,9 @@ public class ChangeInfo extends JavaScriptObject {
public final native String name() /*-{ return this.name; }-*/;
public final native CommitInfo commit() /*-{ return this.commit; }-*/;
public final native boolean has_files() /*-{ return this.hasOwnProperty('files') }-*/;
public final native NativeMap<FileInfo> files() /*-{ return this.files; }-*/;
protected EditInfo() {
}
}

View File

@@ -37,11 +37,13 @@ import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.edit.ChangeEdit;
import com.google.gerrit.server.edit.ChangeEditJson;
import com.google.gerrit.server.edit.ChangeEditModifier;
import com.google.gerrit.server.edit.ChangeEditUtil;
import com.google.gerrit.server.patch.PatchListNotAvailableException;
import com.google.gerrit.server.project.InvalidChangeOperationException;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gwtorm.server.OrmException;
@@ -50,6 +52,8 @@ import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.google.inject.assistedinject.Assisted;
import org.kohsuke.args4j.Option;
import java.io.IOException;
@Singleton
@@ -61,14 +65,14 @@ public class ChangeEdits implements
private final DynamicMap<RestView<ChangeEditResource>> views;
private final Create.Factory createFactory;
private final DeleteEdit.Factory deleteEditFactory;
private final Detail detail;
private final Provider<Detail> detail;
private final ChangeEditUtil editUtil;
private final Post post;
@Inject
ChangeEdits(DynamicMap<RestView<ChangeEditResource>> views,
Create.Factory createFactory,
Detail detail,
Provider<Detail> detail,
ChangeEditUtil editUtil,
Post post,
DeleteEdit.Factory deleteEditFactory) {
@@ -87,7 +91,7 @@ public class ChangeEdits implements
@Override
public RestView<ChangeResource> list() {
return detail;
return detail.get();
}
@Override
@@ -236,28 +240,58 @@ public class ChangeEdits implements
}
}
@Singleton
static class Detail implements RestReadView<ChangeResource> {
private final ChangeEditUtil editUtil;
private final ChangeEditJson editJson;
private final FileInfoJson fileInfoJson;
private final Revisions revisions;
@Option(name = "--base", metaVar = "revision-id")
String base;
@Option(name = "--list", metaVar = "LIST")
boolean list;
@Inject
Detail(ChangeEditJson editJson,
ChangeEditUtil editUtil) {
Detail(ChangeEditUtil editUtil,
ChangeEditJson editJson,
FileInfoJson fileInfoJson,
Revisions revisions) {
this.editJson = editJson;
this.editUtil = editUtil;
this.fileInfoJson = fileInfoJson;
this.revisions = revisions;
}
@Override
public Response<EditInfo> apply(ChangeResource rsrc) throws AuthException,
IOException, NoSuchChangeException, InvalidChangeOperationException,
ResourceNotFoundException {
IOException, InvalidChangeOperationException,
ResourceNotFoundException, OrmException {
Optional<ChangeEdit> edit = editUtil.byChange(rsrc.getChange());
if (edit.isPresent()) {
return Response.ok(editJson.toEditInfo(edit.get()));
}
if (!edit.isPresent()) {
return Response.none();
}
EditInfo editInfo = editJson.toEditInfo(edit.get());
if (list) {
PatchSet basePatchSet = null;
if (base != null) {
RevisionResource baseResource = revisions.parse(
rsrc, IdString.fromDecoded(base));
basePatchSet = baseResource.getPatchSet();
}
try {
editInfo.files =
fileInfoJson.toFileInfoMap(
rsrc.getChange(),
edit.get().getRevision(),
basePatchSet);
} catch (PatchListNotAvailableException e) {
throw new ResourceNotFoundException(e.getMessage());
}
}
return Response.ok(editInfo);
}
}
/**

View File

@@ -21,6 +21,7 @@ import com.google.gerrit.reviewdb.client.AccountDiffPreference.Whitespace;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.RevId;
import com.google.gerrit.server.patch.PatchList;
import com.google.gerrit.server.patch.PatchListCache;
import com.google.gerrit.server.patch.PatchListEntry;
@@ -44,15 +45,15 @@ public class FileInfoJson {
Map<String, FileInfo> toFileInfoMap(Change change, PatchSet patchSet)
throws PatchListNotAvailableException {
return toFileInfoMap(change, patchSet, null);
return toFileInfoMap(change, patchSet.getRevision(), null);
}
Map<String, FileInfo> toFileInfoMap(Change change, PatchSet patchSet, @Nullable PatchSet base)
Map<String, FileInfo> toFileInfoMap(Change change, RevId revision, @Nullable PatchSet base)
throws PatchListNotAvailableException {
ObjectId a = (base == null)
? null
: ObjectId.fromString(base.getRevision().get());
ObjectId b = ObjectId.fromString(patchSet.getRevision().get());
ObjectId b = ObjectId.fromString(revision.get());
PatchList list = patchListCache.get(
new PatchListKey(change.getProject(), a, b, Whitespace.IGNORE_NONE));

View File

@@ -141,7 +141,7 @@ public class Files implements ChildCollection<RevisionResource, FileResource> {
try {
Response<Map<String, FileInfo>> r = Response.ok(fileInfoJson.toFileInfoMap(
resource.getChange(),
resource.getPatchSet(),
resource.getPatchSet().getRevision(),
basePatchSet));
if (resource.isCacheable()) {
r.caching(CacheControl.PRIVATE(7, TimeUnit.DAYS));