Add Follow-Up change UiAction to change screen
Change-Id: If4c9ef331a4646c736720f22fa9f921962f7147f
This commit is contained in:
parent
0619f65b17
commit
ceef9ffcda
@ -39,5 +39,6 @@ public class ChangeInfo {
|
||||
public Map<String, LabelInfo> labels;
|
||||
public Collection<ChangeMessageInfo> messages;
|
||||
public Map<String, RevisionInfo> revisions;
|
||||
public String baseChange;
|
||||
public int _number;
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ class CreateChangeAction {
|
||||
@Override
|
||||
public void onSend() {
|
||||
ChangeApi.createChange(project, getDestinationBranch(),
|
||||
message.getText(),
|
||||
message.getText(), null,
|
||||
new GerritCallback<ChangeInfo>() {
|
||||
@Override
|
||||
public void onSuccess(ChangeInfo result) {
|
||||
|
@ -39,7 +39,7 @@ class Actions extends Composite {
|
||||
private static final String[] CORE = {
|
||||
"abandon", "restore", "revert", "topic",
|
||||
"cherrypick", "submit", "rebase", "message",
|
||||
"publish", "/"};
|
||||
"publish", "followup", "/"};
|
||||
|
||||
interface Binder extends UiBinder<FlowPanel, Actions> {}
|
||||
private static final Binder uiBinder = GWT.create(Binder.class);
|
||||
@ -61,12 +61,17 @@ class Actions extends Composite {
|
||||
@UiField Button restore;
|
||||
private RestoreAction restoreAction;
|
||||
|
||||
@UiField Button followUp;
|
||||
private FollowUpAction followUpAction;
|
||||
|
||||
private Change.Id changeId;
|
||||
private ChangeInfo changeInfo;
|
||||
private String revision;
|
||||
private String project;
|
||||
private String subject;
|
||||
private String message;
|
||||
private String branch;
|
||||
private String key;
|
||||
private boolean canSubmit;
|
||||
|
||||
Actions() {
|
||||
@ -84,6 +89,8 @@ class Actions extends Composite {
|
||||
project = info.project();
|
||||
subject = commit.subject();
|
||||
message = commit.message();
|
||||
branch = info.branch();
|
||||
key = info.change_id();
|
||||
changeInfo = info;
|
||||
|
||||
initChangeActions(info, hasUser);
|
||||
@ -102,6 +109,7 @@ class Actions extends Composite {
|
||||
a2b(actions, "abandon", abandon);
|
||||
a2b(actions, "restore", restore);
|
||||
a2b(actions, "revert", revert);
|
||||
a2b(actions, "followup", followUp);
|
||||
for (String id : filterNonCore(actions)) {
|
||||
add(new ActionButton(info, actions.get(id)));
|
||||
}
|
||||
@ -176,6 +184,15 @@ class Actions extends Composite {
|
||||
return submit.isVisible() && submit.isEnabled();
|
||||
}
|
||||
|
||||
@UiHandler("followUp")
|
||||
void onFollowUp(ClickEvent e) {
|
||||
if (followUpAction == null) {
|
||||
followUpAction = new FollowUpAction(followUp, project,
|
||||
branch, key);
|
||||
}
|
||||
followUpAction.show();
|
||||
}
|
||||
|
||||
@UiHandler("abandon")
|
||||
void onAbandon(ClickEvent e) {
|
||||
if (abandonAction == null) {
|
||||
|
@ -108,6 +108,9 @@ limitations under the License.
|
||||
<g:Button ui:field='restore' styleName='{style.red}' visible='false'>
|
||||
<div><ui:msg>Restore</ui:msg></div>
|
||||
</g:Button>
|
||||
<g:Button ui:field='followUp' styleName='' visible='false'>
|
||||
<div><ui:msg>Follow-Up</ui:msg></div>
|
||||
</g:Button>
|
||||
|
||||
<g:Button ui:field='submit' styleName='{style.submit}' visible='false'/>
|
||||
</g:FlowPanel>
|
||||
|
@ -0,0 +1,46 @@
|
||||
// Copyright (C) 2013 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package com.google.gerrit.client.change;
|
||||
|
||||
import com.google.gerrit.client.Gerrit;
|
||||
import com.google.gerrit.client.changes.ChangeApi;
|
||||
import com.google.gerrit.client.changes.ChangeInfo;
|
||||
import com.google.gerrit.client.rpc.GerritCallback;
|
||||
import com.google.gerrit.common.PageLinks;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
|
||||
class FollowUpAction extends ActionMessageBox {
|
||||
private final String project;
|
||||
private final String branch;
|
||||
private final String base;
|
||||
|
||||
FollowUpAction(Button b, String project, String branch, String key) {
|
||||
super(b);
|
||||
this.project = project;
|
||||
this.branch = branch;
|
||||
this.base = project + "~" + branch + "~" + key;
|
||||
}
|
||||
|
||||
void send(String message) {
|
||||
ChangeApi.createChange(project, branch, message, base,
|
||||
new GerritCallback<ChangeInfo>() {
|
||||
@Override
|
||||
public void onSuccess(ChangeInfo result) {
|
||||
Gerrit.display(PageLinks.toChange(result.legacy_id()));
|
||||
hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -36,11 +36,12 @@ public class ChangeApi {
|
||||
|
||||
/** Create a new change. */
|
||||
public static void createChange(String project, String branch,
|
||||
String subject, AsyncCallback<ChangeInfo> cb) {
|
||||
String subject, String base, AsyncCallback<ChangeInfo> cb) {
|
||||
CreateChangeInput input = CreateChangeInput.create();
|
||||
input.project(emptyToNull(project));
|
||||
input.branch(emptyToNull(branch));
|
||||
input.subject(emptyToNull(subject));
|
||||
input.base_change(emptyToNull(base));
|
||||
|
||||
new RestApi("/changes/").post(input, cb);
|
||||
}
|
||||
@ -213,6 +214,7 @@ public class ChangeApi {
|
||||
public final native void branch(String b) /*-{ if(b)this.branch=b; }-*/;
|
||||
public final native void project(String p) /*-{ if(p)this.project=p; }-*/;
|
||||
public final native void subject(String s) /*-{ if(s)this.subject=s; }-*/;
|
||||
public final native void base_change(String b) /*-{ if(b)this.base_change=b; }-*/;
|
||||
|
||||
protected CreateChangeInput() {
|
||||
}
|
||||
|
@ -20,8 +20,10 @@ import static java.util.concurrent.TimeUnit.MINUTES;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.primitives.Ints;
|
||||
import com.google.gerrit.common.errors.EmailException;
|
||||
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gerrit.reviewdb.client.ChangeMessage;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
@ -30,6 +32,7 @@ import com.google.gerrit.reviewdb.client.RevId;
|
||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||
import com.google.gerrit.server.change.ChangeInserter;
|
||||
import com.google.gerrit.server.change.ChangeMessages;
|
||||
import com.google.gerrit.server.change.ChangeTriplet;
|
||||
import com.google.gerrit.server.change.PatchSetInserter;
|
||||
import com.google.gerrit.server.events.CommitReceivedEvent;
|
||||
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
|
||||
@ -516,6 +519,39 @@ public class ChangeUtil {
|
||||
db.patchSets().delete(Collections.singleton(patch));
|
||||
}
|
||||
|
||||
public List<Change> findChanges(String id)
|
||||
throws OrmException, ResourceNotFoundException {
|
||||
// Try legacy id
|
||||
if (id.matches("^[1-9][0-9]*$")) {
|
||||
Change c = db.get().changes().get(Change.Id.parse(id));
|
||||
if (c != null) {
|
||||
return ImmutableList.of(c);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// Try isolated changeId
|
||||
if (!id.contains("~")) {
|
||||
Change.Key key = new Change.Key(id);
|
||||
if (key.get().length() == 41) {
|
||||
return db.get().changes().byKey(key).toList();
|
||||
} else {
|
||||
return db.get().changes().byKeyRange(key, key.max()).toList();
|
||||
}
|
||||
}
|
||||
|
||||
// Try change triplet
|
||||
ChangeTriplet triplet;
|
||||
try {
|
||||
triplet = new ChangeTriplet(id);
|
||||
} catch (ChangeTriplet.ParseException e) {
|
||||
throw new ResourceNotFoundException(id);
|
||||
}
|
||||
return db.get().changes().byBranchKey(
|
||||
triplet.getBranchNameKey(),
|
||||
triplet.getChangeKey()).toList();
|
||||
}
|
||||
|
||||
private IdentifiedUser user() {
|
||||
return (IdentifiedUser) userProvider.get();
|
||||
}
|
||||
|
@ -62,6 +62,7 @@ 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;
|
||||
@ -331,6 +332,14 @@ public class ChangeJson {
|
||||
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;
|
||||
}
|
||||
|
@ -14,7 +14,6 @@
|
||||
|
||||
package com.google.gerrit.server.change;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.gerrit.extensions.registration.DynamicMap;
|
||||
import com.google.gerrit.extensions.restapi.AcceptsPost;
|
||||
import com.google.gerrit.extensions.restapi.IdString;
|
||||
@ -24,7 +23,7 @@ import com.google.gerrit.extensions.restapi.RestCollection;
|
||||
import com.google.gerrit.extensions.restapi.RestView;
|
||||
import com.google.gerrit.extensions.restapi.TopLevelResource;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||
import com.google.gerrit.server.ChangeUtil;
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
import com.google.gerrit.server.project.ChangeControl;
|
||||
import com.google.gerrit.server.project.NoSuchChangeException;
|
||||
@ -34,33 +33,32 @@ import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@Singleton
|
||||
public class ChangesCollection implements
|
||||
RestCollection<TopLevelResource, ChangeResource>,
|
||||
AcceptsPost<TopLevelResource> {
|
||||
private final Provider<ReviewDb> db;
|
||||
private final Provider<CurrentUser> user;
|
||||
private final ChangeControl.GenericFactory changeControlFactory;
|
||||
private final Provider<QueryChanges> queryFactory;
|
||||
private final DynamicMap<RestView<ChangeResource>> views;
|
||||
private final ChangeUtil changeUtil;
|
||||
private final CreateChange createChange;
|
||||
|
||||
@Inject
|
||||
ChangesCollection(
|
||||
Provider<ReviewDb> dbProvider,
|
||||
Provider<CurrentUser> user,
|
||||
ChangeControl.GenericFactory changeControlFactory,
|
||||
Provider<QueryChanges> queryFactory,
|
||||
DynamicMap<RestView<ChangeResource>> views,
|
||||
ChangeUtil changeUtil,
|
||||
CreateChange createChange) {
|
||||
this.db = dbProvider;
|
||||
this.user = user;
|
||||
this.changeControlFactory = changeControlFactory;
|
||||
this.queryFactory = queryFactory;
|
||||
this.views = views;
|
||||
this.changeUtil = changeUtil;
|
||||
this.createChange = createChange;
|
||||
}
|
||||
|
||||
@ -77,7 +75,7 @@ public class ChangesCollection implements
|
||||
@Override
|
||||
public ChangeResource parse(TopLevelResource root, IdString id)
|
||||
throws ResourceNotFoundException, OrmException {
|
||||
List<Change> changes = findChanges(id.encoded());
|
||||
List<Change> changes = changeUtil.findChanges(id.encoded());
|
||||
if (changes.size() != 1) {
|
||||
throw new ResourceNotFoundException(id);
|
||||
}
|
||||
@ -101,39 +99,6 @@ public class ChangesCollection implements
|
||||
return new ChangeResource(control);
|
||||
}
|
||||
|
||||
private List<Change> findChanges(String id)
|
||||
throws OrmException, ResourceNotFoundException {
|
||||
// Try legacy id
|
||||
if (id.matches("^[1-9][0-9]*$")) {
|
||||
Change c = db.get().changes().get(Change.Id.parse(id));
|
||||
if (c != null) {
|
||||
return ImmutableList.of(c);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// Try isolated changeId
|
||||
if (!id.contains("~")) {
|
||||
Change.Key key = new Change.Key(id);
|
||||
if (key.get().length() == 41) {
|
||||
return db.get().changes().byKey(key).toList();
|
||||
} else {
|
||||
return db.get().changes().byKeyRange(key, key.max()).toList();
|
||||
}
|
||||
}
|
||||
|
||||
// Try change triplet
|
||||
ChangeTriplet triplet;
|
||||
try {
|
||||
triplet = new ChangeTriplet(id);
|
||||
} catch (ChangeTriplet.ParseException e) {
|
||||
throw new ResourceNotFoundException(id);
|
||||
}
|
||||
return db.get().changes().byBranchKey(
|
||||
triplet.getBranchNameKey(),
|
||||
triplet.getChangeKey()).toList();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public CreateChange post(TopLevelResource parent) throws RestApiException {
|
||||
|
@ -15,11 +15,13 @@
|
||||
package com.google.gerrit.server.change;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.gerrit.common.data.Capable;
|
||||
import com.google.gerrit.extensions.common.ChangeInfo;
|
||||
import com.google.gerrit.extensions.common.ChangeStatus;
|
||||
import com.google.gerrit.extensions.restapi.AuthException;
|
||||
import com.google.gerrit.extensions.restapi.BadRequestException;
|
||||
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
||||
import com.google.gerrit.extensions.restapi.Response;
|
||||
import com.google.gerrit.extensions.restapi.RestModifyView;
|
||||
import com.google.gerrit.extensions.restapi.TopLevelResource;
|
||||
@ -29,6 +31,7 @@ import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||
import com.google.gerrit.server.ChangeUtil;
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
import com.google.gerrit.server.GerritPersonIdent;
|
||||
import com.google.gerrit.server.IdentifiedUser;
|
||||
@ -80,6 +83,7 @@ public class CreateChange implements
|
||||
private final CommitValidators.Factory commitValidatorsFactory;
|
||||
private final ChangeInserter.Factory changeInserterFactory;
|
||||
private final ChangeJson json;
|
||||
private final ChangeUtil changeUtil;
|
||||
|
||||
@Inject
|
||||
CreateChange(Provider<ReviewDb> db,
|
||||
@ -89,7 +93,8 @@ public class CreateChange implements
|
||||
ProjectsCollection projectsCollection,
|
||||
CommitValidators.Factory commitValidatorsFactory,
|
||||
ChangeInserter.Factory changeInserterFactory,
|
||||
ChangeJson json) {
|
||||
ChangeJson json,
|
||||
ChangeUtil changeUtil) {
|
||||
this.db = db;
|
||||
this.gitManager = gitManager;
|
||||
this.serverTimeZone = myIdent.getTimeZone();
|
||||
@ -98,13 +103,14 @@ public class CreateChange implements
|
||||
this.commitValidatorsFactory = commitValidatorsFactory;
|
||||
this.changeInserterFactory = changeInserterFactory;
|
||||
this.json = json;
|
||||
this.changeUtil = changeUtil;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response<ChangeJson.ChangeInfo> apply(TopLevelResource parent,
|
||||
ChangeInfo input) throws AuthException, OrmException,
|
||||
BadRequestException, UnprocessableEntityException, IOException,
|
||||
InvalidChangeOperationException {
|
||||
InvalidChangeOperationException, ResourceNotFoundException {
|
||||
|
||||
if (Strings.isNullOrEmpty(input.project)) {
|
||||
throw new BadRequestException("project must be non-empty");
|
||||
@ -148,17 +154,32 @@ public class CreateChange implements
|
||||
try {
|
||||
RevWalk rw = new RevWalk(git);
|
||||
try {
|
||||
Ref destRef = git.getRef(refName);
|
||||
if (destRef == null) {
|
||||
throw new UnprocessableEntityException(String.format(
|
||||
"Branch %s does not exist.", refName));
|
||||
ObjectId parentCommit;
|
||||
if (input.baseChange != null) {
|
||||
List<Change> changes = changeUtil.findChanges(input.baseChange);
|
||||
if (changes.isEmpty()) {
|
||||
throw new InvalidChangeOperationException(
|
||||
"Base change not found: " + input.baseChange);
|
||||
}
|
||||
Change change = Iterables.getOnlyElement(changes);
|
||||
PatchSet ps = db.get().patchSets().get(
|
||||
new PatchSet.Id(change.getId(),
|
||||
change.currentPatchSetId().get()));
|
||||
parentCommit = ObjectId.fromString(ps.getRevision().get());
|
||||
} else {
|
||||
Ref destRef = git.getRef(refName);
|
||||
if (destRef == null) {
|
||||
throw new UnprocessableEntityException(String.format(
|
||||
"Branch %s does not exist.", refName));
|
||||
}
|
||||
parentCommit = destRef.getObjectId();
|
||||
}
|
||||
RevCommit mergeTip = rw.parseCommit(parentCommit);
|
||||
|
||||
Timestamp now = TimeUtil.nowTs();
|
||||
IdentifiedUser me = (IdentifiedUser) userProvider.get();
|
||||
PersonIdent author = me.newCommitterIdent(now, serverTimeZone);
|
||||
|
||||
RevCommit mergeTip = rw.parseCommit(destRef.getObjectId());
|
||||
ObjectId id = ChangeIdUtil.computeChangeId(mergeTip.getTree(),
|
||||
mergeTip, author, author, input.subject);
|
||||
String commitMessage = ChangeIdUtil.insertId(input.subject, id);
|
||||
@ -169,7 +190,7 @@ public class CreateChange implements
|
||||
getChangeId(id, c),
|
||||
new Change.Id(db.get().nextChangeId()),
|
||||
me.getAccountId(),
|
||||
new Branch.NameKey(project, destRef.getName()),
|
||||
new Branch.NameKey(project, refName),
|
||||
now);
|
||||
|
||||
ChangeInserter ins =
|
||||
|
Loading…
Reference in New Issue
Block a user