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
This commit is contained in:
Stefan Beller
2015-02-12 13:40:23 -08:00
committed by David Pursehouse
parent c725966f8b
commit 09cd95dbfd
4 changed files with 69 additions and 39 deletions

View File

@@ -281,8 +281,15 @@ default. Optional fields are:
[[actions]] [[actions]]
-- --
* `CURRENT_ACTIONS`: include information on available actions * `CURRENT_ACTIONS`: include information on available actions
for the change and its current revision. The caller must be for the change and its current revision. Ignored if the caller
authenticated to obtain the available actions. is not authenticated.
--
[[change-actions]]
--
* `CHANGE_ACTIONS`: include information on available
change actions for the change. Ignored if the caller
is not authenticated.
-- --
[[reviewed]] [[reviewed]]

View File

@@ -55,7 +55,10 @@ public enum ListChangesOption {
WEB_LINKS(14), WEB_LINKS(14),
/** Include consistency check results. */ /** Include consistency check results. */
CHECK(15); CHECK(15),
/** Include allowed change actions client could perform. */
CHANGE_ACTIONS(16);
private final int value; private final int value;

View File

@@ -15,9 +15,15 @@
package com.google.gerrit.server.change; package com.google.gerrit.server.change;
import com.google.gerrit.extensions.common.ActionInfo; 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.extensions.webui.UiAction;
import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.extensions.webui.UiActions; import com.google.gerrit.server.extensions.webui.UiActions;
import com.google.gerrit.server.project.ChangeControl;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Provider; import com.google.inject.Provider;
import com.google.inject.Singleton; import com.google.inject.Singleton;
@@ -29,16 +35,55 @@ import java.util.Map;
@Singleton @Singleton
public class ActionJson { public class ActionJson {
private final Revisions revisions; private final Revisions revisions;
private final DynamicMap<RestView<ChangeResource>> changeViews;
@Inject @Inject
ActionJson(Revisions revisions) { ActionJson(
Revisions revisions,
DynamicMap<RestView<ChangeResource>> changeViews) {
this.revisions = revisions; this.revisions = revisions;
this.changeViews = changeViews;
} }
public Map<String, ActionInfo> format(RevisionResource rsrc) { public Map<String, ActionInfo> format(RevisionResource rsrc) {
return toActionMap(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) { private Map<String, ActionInfo> toActionMap(RevisionResource rsrc) {
Map<String, ActionInfo> out = new LinkedHashMap<>(); Map<String, ActionInfo> out = new LinkedHashMap<>();
if (rsrc.getControl().getCurrentUser().isIdentifiedUser()) { if (rsrc.getControl().getCurrentUser().isIdentifiedUser()) {

View File

@@ -17,6 +17,7 @@ package com.google.gerrit.server.change;
import static com.google.gerrit.extensions.client.ListChangesOption.ALL_COMMITS; 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_FILES;
import static com.google.gerrit.extensions.client.ListChangesOption.ALL_REVISIONS; 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.CHECK;
import static com.google.gerrit.extensions.client.ListChangesOption.CURRENT_ACTIONS; import static com.google.gerrit.extensions.client.ListChangesOption.CURRENT_ACTIONS;
import static com.google.gerrit.extensions.client.ListChangesOption.CURRENT_COMMIT; import static com.google.gerrit.extensions.client.ListChangesOption.CURRENT_COMMIT;
@@ -59,7 +60,6 @@ import com.google.gerrit.common.data.SubmitRecord;
import com.google.gerrit.extensions.api.changes.FixInput; import com.google.gerrit.extensions.api.changes.FixInput;
import com.google.gerrit.extensions.client.ListChangesOption; import com.google.gerrit.extensions.client.ListChangesOption;
import com.google.gerrit.extensions.common.AccountInfo; 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.ApprovalInfo;
import com.google.gerrit.extensions.common.ChangeInfo; import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.ChangeMessageInfo; import com.google.gerrit.extensions.common.ChangeMessageInfo;
@@ -73,10 +73,7 @@ import com.google.gerrit.extensions.common.WebLinkInfo;
import com.google.gerrit.extensions.config.DownloadCommand; import com.google.gerrit.extensions.config.DownloadCommand;
import com.google.gerrit.extensions.config.DownloadScheme; import com.google.gerrit.extensions.config.DownloadScheme;
import com.google.gerrit.extensions.registration.DynamicMap; 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.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.Account;
import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.ChangeMessage; import com.google.gerrit.reviewdb.client.ChangeMessage;
@@ -95,7 +92,6 @@ import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.PatchLineCommentsUtil; import com.google.gerrit.server.PatchLineCommentsUtil;
import com.google.gerrit.server.WebLinks; import com.google.gerrit.server.WebLinks;
import com.google.gerrit.server.account.AccountLoader; 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.git.LabelNormalizer;
import com.google.gerrit.server.notedb.ChangeNotes; import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.patch.PatchListNotAvailableException; import com.google.gerrit.server.patch.PatchListNotAvailableException;
@@ -140,13 +136,12 @@ public class ChangeJson {
private final AccountLoader.Factory accountLoaderFactory; private final AccountLoader.Factory accountLoaderFactory;
private final DynamicMap<DownloadScheme> downloadSchemes; private final DynamicMap<DownloadScheme> downloadSchemes;
private final DynamicMap<DownloadCommand> downloadCommands; private final DynamicMap<DownloadCommand> downloadCommands;
private final DynamicMap<RestView<ChangeResource>> changeViews;
private final Revisions revisions;
private final WebLinks webLinks; private final WebLinks webLinks;
private final EnumSet<ListChangesOption> options; private final EnumSet<ListChangesOption> options;
private final ChangeMessagesUtil cmUtil; private final ChangeMessagesUtil cmUtil;
private final PatchLineCommentsUtil plcUtil; private final PatchLineCommentsUtil plcUtil;
private final Provider<ConsistencyChecker> checkerProvider; private final Provider<ConsistencyChecker> checkerProvider;
private final ActionJson actionJson;
private AccountLoader accountLoader; private AccountLoader accountLoader;
private FixInput fix; private FixInput fix;
@@ -164,12 +159,11 @@ public class ChangeJson {
AccountLoader.Factory ailf, AccountLoader.Factory ailf,
DynamicMap<DownloadScheme> downloadSchemes, DynamicMap<DownloadScheme> downloadSchemes,
DynamicMap<DownloadCommand> downloadCommands, DynamicMap<DownloadCommand> downloadCommands,
DynamicMap<RestView<ChangeResource>> changeViews,
Revisions revisions,
WebLinks webLinks, WebLinks webLinks,
ChangeMessagesUtil cmUtil, ChangeMessagesUtil cmUtil,
PatchLineCommentsUtil plcUtil, PatchLineCommentsUtil plcUtil,
Provider<ConsistencyChecker> checkerProvider) { Provider<ConsistencyChecker> checkerProvider,
ActionJson actionJson) {
this.db = db; this.db = db;
this.labelNormalizer = ln; this.labelNormalizer = ln;
this.userProvider = user; this.userProvider = user;
@@ -181,12 +175,11 @@ public class ChangeJson {
this.accountLoaderFactory = ailf; this.accountLoaderFactory = ailf;
this.downloadSchemes = downloadSchemes; this.downloadSchemes = downloadSchemes;
this.downloadCommands = downloadCommands; this.downloadCommands = downloadCommands;
this.changeViews = changeViews;
this.revisions = revisions;
this.webLinks = webLinks; this.webLinks = webLinks;
this.cmUtil = cmUtil; this.cmUtil = cmUtil;
this.plcUtil = plcUtil; this.plcUtil = plcUtil;
this.checkerProvider = checkerProvider; this.checkerProvider = checkerProvider;
this.actionJson = actionJson;
options = EnumSet.noneOf(ListChangesOption.class); options = EnumSet.noneOf(ListChangesOption.class);
} }
@@ -419,22 +412,8 @@ public class ChangeJson {
} }
} }
if (has(CURRENT_ACTIONS) && userProvider.get().isIdentifiedUser()) { if (has(CURRENT_ACTIONS) || has(CHANGE_ACTIONS)) {
out.actions = Maps.newTreeMap(); actionJson.addChangeActions(out, ctl);
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));
}
} }
return out; return out;
@@ -907,13 +886,9 @@ public class ChangeJson {
if ((out.isCurrent || (out.draft != null && out.draft)) if ((out.isCurrent || (out.draft != null && out.draft))
&& has(CURRENT_ACTIONS) && has(CURRENT_ACTIONS)
&& userProvider.get().isIdentifiedUser()) { && userProvider.get().isIdentifiedUser()) {
out.actions = Maps.newTreeMap();
for (UiAction.Description d : UiActions.from( actionJson.addRevisionActions(out,
revisions, new RevisionResource(new ChangeResource(ctl), in));
new RevisionResource(new ChangeResource(ctl), in),
userProvider)) {
out.actions.put(d.getId(), new ActionInfo(d));
}
} }
if (has(DRAFT_COMMENTS) if (has(DRAFT_COMMENTS)