Add new CHANGE_ACTIONS option to /changes/X/detail REST API call
This will move action related JSON processing into the ActionJson class
as well.
Change-Id: I291727762d2f08d00484ca8ce8805624042ab4e8
diff --git a/Documentation/rest-api-changes.txt b/Documentation/rest-api-changes.txt
index 115cee5..284cc83 100644
--- a/Documentation/rest-api-changes.txt
+++ b/Documentation/rest-api-changes.txt
@@ -281,8 +281,15 @@
[[actions]]
--
* `CURRENT_ACTIONS`: include information on available actions
- for the change and its current revision. The caller must be
- authenticated to obtain the available actions.
+ for the change and its current revision. Ignored if the caller
+ is not authenticated.
+--
+
+[[change-actions]]
+--
+* `CHANGE_ACTIONS`: include information on available
+ change actions for the change. Ignored if the caller
+ is not authenticated.
--
[[reviewed]]
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/client/ListChangesOption.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/client/ListChangesOption.java
index 1049d6a..54617a7 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/client/ListChangesOption.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/client/ListChangesOption.java
@@ -55,7 +55,10 @@
WEB_LINKS(14),
/** Include consistency check results. */
- CHECK(15);
+ CHECK(15),
+
+ /** Include allowed change actions client could perform. */
+ CHANGE_ACTIONS(16);
private final int value;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/ActionJson.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/ActionJson.java
index 24837aab..023173e 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/ActionJson.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/ActionJson.java
@@ -15,9 +15,15 @@
package com.google.gerrit.server.change;
import com.google.gerrit.extensions.common.ActionInfo;
+import com.google.gerrit.extensions.common.ChangeInfo;
+import com.google.gerrit.extensions.common.RevisionInfo;
+import com.google.gerrit.extensions.registration.DynamicMap;
+import com.google.gerrit.extensions.restapi.RestView;
+import com.google.gerrit.extensions.webui.PrivateInternals_UiActionDescription;
import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.extensions.webui.UiActions;
+import com.google.gerrit.server.project.ChangeControl;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
@@ -29,16 +35,55 @@
@Singleton
public class ActionJson {
private final Revisions revisions;
+ private final DynamicMap<RestView<ChangeResource>> changeViews;
@Inject
- ActionJson(Revisions revisions) {
+ ActionJson(
+ Revisions revisions,
+ DynamicMap<RestView<ChangeResource>> changeViews) {
this.revisions = revisions;
+ this.changeViews = changeViews;
}
public Map<String, ActionInfo> format(RevisionResource rsrc) {
return toActionMap(rsrc);
}
+ public ChangeInfo addChangeActions(ChangeInfo to, ChangeControl ctl) {
+ to.actions = toActionMap(ctl);
+ return to;
+ }
+
+ public RevisionInfo addRevisionActions(RevisionInfo to,
+ RevisionResource rsrc) {
+ to.actions = toActionMap(rsrc);
+ return to;
+ }
+
+ private Map<String, ActionInfo> toActionMap(ChangeControl ctl) {
+ Map<String, ActionInfo> out = new LinkedHashMap<>();
+ if (!ctl.getCurrentUser().isIdentifiedUser()) {
+ return out;
+ }
+
+ Provider<CurrentUser> userProvider = Providers.of(ctl.getCurrentUser());
+ for (UiAction.Description d : UiActions.from(
+ changeViews,
+ new ChangeResource(ctl),
+ userProvider)) {
+ out.put(d.getId(), new ActionInfo(d));
+ }
+ // TODO(sbeller): why do we need to treat followup specially here?
+ if (ctl.getChange().getStatus().isOpen()) {
+ UiAction.Description descr = new UiAction.Description();
+ PrivateInternals_UiActionDescription.setId(descr, "followup");
+ PrivateInternals_UiActionDescription.setMethod(descr, "POST");
+ descr.setTitle("Create follow-up change");
+ out.put(descr.getId(), new ActionInfo(descr));
+ }
+ return out;
+ }
+
private Map<String, ActionInfo> toActionMap(RevisionResource rsrc) {
Map<String, ActionInfo> out = new LinkedHashMap<>();
if (rsrc.getControl().getCurrentUser().isIdentifiedUser()) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeJson.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeJson.java
index 662406a..86a50a6 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeJson.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeJson.java
@@ -17,6 +17,7 @@
import static com.google.gerrit.extensions.client.ListChangesOption.ALL_COMMITS;
import static com.google.gerrit.extensions.client.ListChangesOption.ALL_FILES;
import static com.google.gerrit.extensions.client.ListChangesOption.ALL_REVISIONS;
+import static com.google.gerrit.extensions.client.ListChangesOption.CHANGE_ACTIONS;
import static com.google.gerrit.extensions.client.ListChangesOption.CHECK;
import static com.google.gerrit.extensions.client.ListChangesOption.CURRENT_ACTIONS;
import static com.google.gerrit.extensions.client.ListChangesOption.CURRENT_COMMIT;
@@ -59,7 +60,6 @@
import com.google.gerrit.extensions.api.changes.FixInput;
import com.google.gerrit.extensions.client.ListChangesOption;
import com.google.gerrit.extensions.common.AccountInfo;
-import com.google.gerrit.extensions.common.ActionInfo;
import com.google.gerrit.extensions.common.ApprovalInfo;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.ChangeMessageInfo;
@@ -73,10 +73,7 @@
import com.google.gerrit.extensions.config.DownloadCommand;
import com.google.gerrit.extensions.config.DownloadScheme;
import com.google.gerrit.extensions.registration.DynamicMap;
-import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.extensions.restapi.Url;
-import com.google.gerrit.extensions.webui.PrivateInternals_UiActionDescription;
-import com.google.gerrit.extensions.webui.UiAction;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.ChangeMessage;
@@ -95,7 +92,6 @@
import com.google.gerrit.server.PatchLineCommentsUtil;
import com.google.gerrit.server.WebLinks;
import com.google.gerrit.server.account.AccountLoader;
-import com.google.gerrit.server.extensions.webui.UiActions;
import com.google.gerrit.server.git.LabelNormalizer;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.patch.PatchListNotAvailableException;
@@ -140,13 +136,12 @@
private final AccountLoader.Factory accountLoaderFactory;
private final DynamicMap<DownloadScheme> downloadSchemes;
private final DynamicMap<DownloadCommand> downloadCommands;
- private final DynamicMap<RestView<ChangeResource>> changeViews;
- private final Revisions revisions;
private final WebLinks webLinks;
private final EnumSet<ListChangesOption> options;
private final ChangeMessagesUtil cmUtil;
private final PatchLineCommentsUtil plcUtil;
private final Provider<ConsistencyChecker> checkerProvider;
+ private final ActionJson actionJson;
private AccountLoader accountLoader;
private FixInput fix;
@@ -164,12 +159,11 @@
AccountLoader.Factory ailf,
DynamicMap<DownloadScheme> downloadSchemes,
DynamicMap<DownloadCommand> downloadCommands,
- DynamicMap<RestView<ChangeResource>> changeViews,
- Revisions revisions,
WebLinks webLinks,
ChangeMessagesUtil cmUtil,
PatchLineCommentsUtil plcUtil,
- Provider<ConsistencyChecker> checkerProvider) {
+ Provider<ConsistencyChecker> checkerProvider,
+ ActionJson actionJson) {
this.db = db;
this.labelNormalizer = ln;
this.userProvider = user;
@@ -181,12 +175,11 @@
this.accountLoaderFactory = ailf;
this.downloadSchemes = downloadSchemes;
this.downloadCommands = downloadCommands;
- this.changeViews = changeViews;
- this.revisions = revisions;
this.webLinks = webLinks;
this.cmUtil = cmUtil;
this.plcUtil = plcUtil;
this.checkerProvider = checkerProvider;
+ this.actionJson = actionJson;
options = EnumSet.noneOf(ListChangesOption.class);
}
@@ -419,22 +412,8 @@
}
}
- if (has(CURRENT_ACTIONS) && userProvider.get().isIdentifiedUser()) {
- out.actions = Maps.newTreeMap();
- for (UiAction.Description d : UiActions.from(
- changeViews,
- new ChangeResource(ctl),
- userProvider)) {
- out.actions.put(d.getId(), new ActionInfo(d));
- }
- if (userProvider.get().isIdentifiedUser()
- && in.getStatus().isOpen()) {
- UiAction.Description descr = new UiAction.Description();
- PrivateInternals_UiActionDescription.setId(descr, "followup");
- PrivateInternals_UiActionDescription.setMethod(descr, "POST");
- descr.setTitle("Create follow-up change");
- out.actions.put(descr.getId(), new ActionInfo(descr));
- }
+ if (has(CURRENT_ACTIONS) || has(CHANGE_ACTIONS)) {
+ actionJson.addChangeActions(out, ctl);
}
return out;
@@ -907,13 +886,9 @@
if ((out.isCurrent || (out.draft != null && out.draft))
&& has(CURRENT_ACTIONS)
&& userProvider.get().isIdentifiedUser()) {
- out.actions = Maps.newTreeMap();
- for (UiAction.Description d : UiActions.from(
- revisions,
- new RevisionResource(new ChangeResource(ctl), in),
- userProvider)) {
- out.actions.put(d.getId(), new ActionInfo(d));
- }
+
+ actionJson.addRevisionActions(out,
+ new RevisionResource(new ChangeResource(ctl), in));
}
if (has(DRAFT_COMMENTS)