ChangeScreen2: allow edit commit message
Add new "Edit Message" button in change header and bind it to "e" shortcut. Add a new UiAction as REST API endpoint to create a new revision with updated commit message. Reload the screen on success. Change-Id: Ic555f16efba4783eca9684340b27f9d58b1482bb
This commit is contained in:
		 David Ostrovsky
					David Ostrovsky
				
			
				
					committed by
					
						 Shawn Pearce
						Shawn Pearce
					
				
			
			
				
	
			
			
			 Shawn Pearce
						Shawn Pearce
					
				
			
						parent
						
							4139c3a41d
						
					
				
				
					commit
					60400e2bc1
				
			| @@ -35,7 +35,7 @@ import java.util.TreeSet; | |||||||
| class Actions extends Composite { | class Actions extends Composite { | ||||||
|   private static final String[] CORE = { |   private static final String[] CORE = { | ||||||
|     "abandon", "restore", "revert", "topic", |     "abandon", "restore", "revert", "topic", | ||||||
|     "cherrypick", "submit", "rebase"}; |     "cherrypick", "submit", "rebase", "message"}; | ||||||
|  |  | ||||||
|   interface Binder extends UiBinder<FlowPanel, Actions> {} |   interface Binder extends UiBinder<FlowPanel, Actions> {} | ||||||
|   private static Binder uiBinder = GWT.create(Binder.class); |   private static Binder uiBinder = GWT.create(Binder.class); | ||||||
|   | |||||||
| @@ -19,6 +19,7 @@ import com.google.gerrit.client.Gerrit; | |||||||
| import com.google.gerrit.client.account.AccountInfo; | import com.google.gerrit.client.account.AccountInfo; | ||||||
| import com.google.gerrit.client.changes.ChangeApi; | import com.google.gerrit.client.changes.ChangeApi; | ||||||
| import com.google.gerrit.client.changes.ChangeInfo; | import com.google.gerrit.client.changes.ChangeInfo; | ||||||
|  | import com.google.gerrit.client.changes.ChangeInfo.ActionInfo; | ||||||
| import com.google.gerrit.client.changes.ChangeInfo.ApprovalInfo; | import com.google.gerrit.client.changes.ChangeInfo.ApprovalInfo; | ||||||
| import com.google.gerrit.client.changes.ChangeInfo.CommitInfo; | import com.google.gerrit.client.changes.ChangeInfo.CommitInfo; | ||||||
| import com.google.gerrit.client.changes.ChangeInfo.LabelInfo; | import com.google.gerrit.client.changes.ChangeInfo.LabelInfo; | ||||||
| @@ -148,8 +149,10 @@ public class ChangeScreen2 extends Screen { | |||||||
|   @UiField Button reply; |   @UiField Button reply; | ||||||
|   @UiField Button expandAll; |   @UiField Button expandAll; | ||||||
|   @UiField Button collapseAll; |   @UiField Button collapseAll; | ||||||
|  |   @UiField Button editMessage; | ||||||
|   @UiField QuickApprove quickApprove; |   @UiField QuickApprove quickApprove; | ||||||
|   private ReplyAction replyAction; |   private ReplyAction replyAction; | ||||||
|  |   private EditMessageAction editMessageAction; | ||||||
|  |  | ||||||
|   public ChangeScreen2(Change.Id changeId, String revision, boolean openReplyBox) { |   public ChangeScreen2(Change.Id changeId, String revision, boolean openReplyBox) { | ||||||
|     this.changeId = changeId; |     this.changeId = changeId; | ||||||
| @@ -241,6 +244,26 @@ public class ChangeScreen2 extends Screen { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   private void initEditMessageAction() { | ||||||
|  |     NativeMap<ActionInfo> actions = changeInfo.revision(revision).actions(); | ||||||
|  |     if (actions != null && actions.containsKey("message")) { | ||||||
|  |       editMessage.setVisible(true); | ||||||
|  |       editMessageAction = new EditMessageAction( | ||||||
|  |           changeInfo.legacy_id(), | ||||||
|  |           revision, | ||||||
|  |           changeInfo.revision(revision).commit().message(), | ||||||
|  |           style, | ||||||
|  |           editMessage, | ||||||
|  |           reply); | ||||||
|  |       keysAction.add(new KeyCommand(0, 'e', Util.C.keyEditMessage()) { | ||||||
|  |         @Override | ||||||
|  |         public void onKeyPress(KeyPressEvent event) { | ||||||
|  |           editMessageAction.onEdit(); | ||||||
|  |         } | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|   @Override |   @Override | ||||||
|   public void registerKeys() { |   public void registerKeys() { | ||||||
|     super.registerKeys(); |     super.registerKeys(); | ||||||
| @@ -325,6 +348,11 @@ public class ChangeScreen2 extends Screen { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   @UiHandler("editMessage") | ||||||
|  |   void onEditMessage(ClickEvent e) { | ||||||
|  |     editMessageAction.onEdit(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   @UiHandler("expandAll") |   @UiHandler("expandAll") | ||||||
|   void onExpandAll(ClickEvent e) { |   void onExpandAll(ClickEvent e) { | ||||||
|     int n = history.getWidgetCount(); |     int n = history.getWidgetCount(); | ||||||
| @@ -566,6 +594,7 @@ public class ChangeScreen2 extends Screen { | |||||||
|     quickApprove.set(info, revision); |     quickApprove.set(info, revision); | ||||||
|  |  | ||||||
|     if (Gerrit.isSignedIn()) { |     if (Gerrit.isSignedIn()) { | ||||||
|  |       initEditMessageAction(); | ||||||
|       replyAction = new ReplyAction(info, revision, style, reply); |       replyAction = new ReplyAction(info, revision, style, reply); | ||||||
|       if (topic.canEdit()) { |       if (topic.canEdit()) { | ||||||
|         keysAction.add(new KeyCommand(0, 't', Util.C.keyEditTopic()) { |         keysAction.add(new KeyCommand(0, 't', Util.C.keyEditTopic()) { | ||||||
|   | |||||||
| @@ -222,6 +222,13 @@ limitations under the License. | |||||||
|             title='Apply score with one click'> |             title='Apply score with one click'> | ||||||
|           <ui:attribute name='title'/> |           <ui:attribute name='title'/> | ||||||
|         </c:QuickApprove> |         </c:QuickApprove> | ||||||
|  |         <g:Button ui:field='editMessage' | ||||||
|  |             styleName='' | ||||||
|  |             visible='false' | ||||||
|  |             title='Edit commit message (Shortcut: e)'> | ||||||
|  |           <ui:attribute name='title'/> | ||||||
|  |           <div><ui:msg>Edit Message</ui:msg></div> | ||||||
|  |         </g:Button> | ||||||
|       </div> |       </div> | ||||||
|       <div class='{style.revisionList}' ui:field='revisionParent'> |       <div class='{style.revisionList}' ui:field='revisionParent'> | ||||||
|         <ui:msg>Revision <g:ListBox ui:field='revisionList'/></ui:msg> |         <ui:msg>Revision <g:ListBox ui:field='revisionList'/></ui:msg> | ||||||
|   | |||||||
| @@ -0,0 +1,80 @@ | |||||||
|  | // 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.reviewdb.client.Change; | ||||||
|  | import com.google.gwt.event.logical.shared.CloseEvent; | ||||||
|  | import com.google.gwt.event.logical.shared.CloseHandler; | ||||||
|  | import com.google.gwt.user.client.ui.PopupPanel; | ||||||
|  | import com.google.gwt.user.client.ui.Widget; | ||||||
|  | import com.google.gwtexpui.globalkey.client.GlobalKey; | ||||||
|  | import com.google.gwtexpui.user.client.PluginSafePopupPanel; | ||||||
|  |  | ||||||
|  | class EditMessageAction { | ||||||
|  |   private final Change.Id changeId; | ||||||
|  |   private final String revision; | ||||||
|  |   private final String originalMessage; | ||||||
|  |   private final ChangeScreen2.Style style; | ||||||
|  |   private final Widget editMessageButton; | ||||||
|  |   private final Widget replyButton; | ||||||
|  |  | ||||||
|  |   private EditMessageBox editBox; | ||||||
|  |   private PopupPanel popup; | ||||||
|  |  | ||||||
|  |   EditMessageAction( | ||||||
|  |       Change.Id changeId, | ||||||
|  |       String revision, | ||||||
|  |       String originalMessage, | ||||||
|  |       ChangeScreen2.Style style, | ||||||
|  |       Widget editButton, | ||||||
|  |       Widget replyButton) { | ||||||
|  |     this.changeId = changeId; | ||||||
|  |     this.revision = revision; | ||||||
|  |     this.originalMessage = originalMessage; | ||||||
|  |     this.style = style; | ||||||
|  |     this.editMessageButton = editButton; | ||||||
|  |     this.replyButton = replyButton; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   void onEdit() { | ||||||
|  |     if (popup != null) { | ||||||
|  |       popup.hide(); | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (editBox == null) { | ||||||
|  |       editBox = new EditMessageBox( | ||||||
|  |           changeId, | ||||||
|  |           revision, | ||||||
|  |           originalMessage); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     final PluginSafePopupPanel p = new PluginSafePopupPanel(true); | ||||||
|  |     p.setStyleName(style.replyBox()); | ||||||
|  |     p.addAutoHidePartner(editMessageButton.getElement()); | ||||||
|  |     p.addCloseHandler(new CloseHandler<PopupPanel>() { | ||||||
|  |       @Override | ||||||
|  |       public void onClose(CloseEvent<PopupPanel> event) { | ||||||
|  |         if (popup == p) { | ||||||
|  |           popup = null; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  |     p.add(editBox); | ||||||
|  |     p.showRelativeTo(replyButton); | ||||||
|  |     GlobalKey.dialog(p); | ||||||
|  |     popup = p; | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -0,0 +1,102 @@ | |||||||
|  | // 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.rpc.GerritCallback; | ||||||
|  | import com.google.gerrit.client.ui.TextBoxChangeListener; | ||||||
|  | import com.google.gerrit.common.PageLinks; | ||||||
|  | import com.google.gerrit.reviewdb.client.Change; | ||||||
|  | import com.google.gwt.core.client.GWT; | ||||||
|  | import com.google.gwt.core.client.JavaScriptObject; | ||||||
|  | import com.google.gwt.core.client.Scheduler; | ||||||
|  | import com.google.gwt.core.client.Scheduler.ScheduledCommand; | ||||||
|  | import com.google.gwt.event.dom.client.ClickEvent; | ||||||
|  | import com.google.gwt.uibinder.client.UiBinder; | ||||||
|  | import com.google.gwt.uibinder.client.UiField; | ||||||
|  | import com.google.gwt.uibinder.client.UiHandler; | ||||||
|  | import com.google.gwt.user.client.ui.Button; | ||||||
|  | import com.google.gwt.user.client.ui.Composite; | ||||||
|  | import com.google.gwt.user.client.ui.HTMLPanel; | ||||||
|  | import com.google.gwt.user.client.ui.PopupPanel; | ||||||
|  | import com.google.gwt.user.client.ui.Widget; | ||||||
|  | import com.google.gwtexpui.globalkey.client.NpTextArea; | ||||||
|  |  | ||||||
|  | class EditMessageBox extends Composite { | ||||||
|  |   interface Binder extends UiBinder<HTMLPanel, EditMessageBox> {} | ||||||
|  |   private static final Binder uiBinder = GWT.create(Binder.class); | ||||||
|  |  | ||||||
|  |   private final Change.Id changeId; | ||||||
|  |   private final String revision; | ||||||
|  |   private String originalMessage; | ||||||
|  |  | ||||||
|  |   @UiField NpTextArea message; | ||||||
|  |   @UiField Button save; | ||||||
|  |   @UiField Button cancel; | ||||||
|  |  | ||||||
|  |   EditMessageBox( | ||||||
|  |       Change.Id changeId, | ||||||
|  |       String revision, | ||||||
|  |       String msg) { | ||||||
|  |     this.changeId = changeId; | ||||||
|  |     this.revision = revision; | ||||||
|  |     this.originalMessage = msg.trim(); | ||||||
|  |     initWidget(uiBinder.createAndBindUi(this)); | ||||||
|  |     new TextBoxChangeListener(message) { | ||||||
|  |       public void onTextChanged(String newText) { | ||||||
|  |         save.setEnabled(!newText.trim() | ||||||
|  |             .equals(originalMessage)); | ||||||
|  |       } | ||||||
|  |     }; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Override | ||||||
|  |   protected void onLoad() { | ||||||
|  |     message.setText(originalMessage); | ||||||
|  |     save.setEnabled(false); | ||||||
|  |     Scheduler.get().scheduleDeferred(new ScheduledCommand() { | ||||||
|  |       @Override | ||||||
|  |       public void execute() { | ||||||
|  |         message.setFocus(true); | ||||||
|  |       }}); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @UiHandler("save") | ||||||
|  |   void onSave(ClickEvent e) { | ||||||
|  |     ChangeApi.message(changeId.get(), revision, message.getText().trim(), | ||||||
|  |         new GerritCallback<JavaScriptObject>() { | ||||||
|  |           @Override | ||||||
|  |           public void onSuccess(JavaScriptObject msg) { | ||||||
|  |             Gerrit.display(PageLinks.toChange2(changeId)); | ||||||
|  |             hide(); | ||||||
|  |           }; | ||||||
|  |         }); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @UiHandler("cancel") | ||||||
|  |   void onCancel(ClickEvent e) { | ||||||
|  |     hide(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   private void hide() { | ||||||
|  |     for (Widget w = getParent(); w != null; w = w.getParent()) { | ||||||
|  |       if (w instanceof PopupPanel) { | ||||||
|  |         ((PopupPanel) w).hide(); | ||||||
|  |         break; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -0,0 +1,51 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <!-- | ||||||
|  | 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. | ||||||
|  | --> | ||||||
|  | <ui:UiBinder | ||||||
|  |     xmlns:ui='urn:ui:com.google.gwt.uibinder' | ||||||
|  |     xmlns:g='urn:import:com.google.gwt.user.client.ui' | ||||||
|  |     xmlns:c='urn:import:com.google.gwtexpui.globalkey.client'> | ||||||
|  |   <ui:with field='res' type='com.google.gerrit.client.change.Resources'/> | ||||||
|  |   <ui:style> | ||||||
|  |     .commitMessage { | ||||||
|  |       background-color: white; | ||||||
|  |       font-family: monospace; | ||||||
|  |     } | ||||||
|  |     .cancel { float: right; } | ||||||
|  |   </ui:style> | ||||||
|  |   <g:HTMLPanel> | ||||||
|  |     <div class='{res.style.section}'> | ||||||
|  |       <c:NpTextArea | ||||||
|  |          visibleLines='30' | ||||||
|  |          characterWidth='72' | ||||||
|  |          styleName='{style.commitMessage}' | ||||||
|  |          ui:field='message'/> | ||||||
|  |     </div> | ||||||
|  |     <div class='{res.style.section}'> | ||||||
|  |       <g:Button ui:field='save' | ||||||
|  |           title='Create new patch set with updated commit message' | ||||||
|  |           styleName='{res.style.button}'> | ||||||
|  |         <ui:attribute name='title'/> | ||||||
|  |         <div><ui:msg>Save</ui:msg></div> | ||||||
|  |       </g:Button> | ||||||
|  |       <g:Button ui:field='cancel' | ||||||
|  |           styleName='{res.style.button}' | ||||||
|  |           addStyleNames='{style.cancel}'> | ||||||
|  |           <div>Cancel</div> | ||||||
|  |       </g:Button> | ||||||
|  |     </div> | ||||||
|  |   </g:HTMLPanel> | ||||||
|  | </ui:UiBinder> | ||||||
| @@ -26,11 +26,6 @@ limitations under the License. | |||||||
|       max-height: 260px; |       max-height: 260px; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     .section { |  | ||||||
|       padding: 5px 5px; |  | ||||||
|       border-bottom: 1px solid #b8b8b8; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     .label_name { |     .label_name { | ||||||
|       font-weight: bold; |       font-weight: bold; | ||||||
|       text-align: left; |       text-align: left; | ||||||
| @@ -46,16 +41,16 @@ limitations under the License. | |||||||
|     } |     } | ||||||
|   </ui:style> |   </ui:style> | ||||||
|   <g:HTMLPanel styleName='{style.replyBox}'> |   <g:HTMLPanel styleName='{style.replyBox}'> | ||||||
|     <div class='{style.section}'> |     <div class='{res.style.section}'> | ||||||
|       <c:NpTextArea |       <c:NpTextArea | ||||||
|          visibleLines='5' |          visibleLines='5' | ||||||
|          characterWidth='70' |          characterWidth='70' | ||||||
|          ui:field='message'/> |          ui:field='message'/> | ||||||
|     </div> |     </div> | ||||||
|     <div class='{style.section}' ui:field='labelsParent'> |     <div class='{res.style.section}' ui:field='labelsParent'> | ||||||
|       <g:Grid ui:field='labelsTable'/> |       <g:Grid ui:field='labelsTable'/> | ||||||
|     </div> |     </div> | ||||||
|     <div class='{style.section}'> |     <div class='{res.style.section}'> | ||||||
|       <g:Button ui:field='send' |       <g:Button ui:field='send' | ||||||
|           title='Send reply (Shortcut: Ctrl-Enter)' |           title='Send reply (Shortcut: Ctrl-Enter)' | ||||||
|           styleName='{res.style.button}'> |           styleName='{res.style.button}'> | ||||||
|   | |||||||
| @@ -33,5 +33,6 @@ public interface Resources extends ClientBundle { | |||||||
|     String button(); |     String button(); | ||||||
|     String popup(); |     String popup(); | ||||||
|     String popupContent(); |     String popupContent(); | ||||||
|  |     String section(); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -49,3 +49,8 @@ | |||||||
|   height: 10px; |   height: 10px; | ||||||
|   line-height: 10px; |   line-height: 10px; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | .section { | ||||||
|  |   padding: 5px 5px; | ||||||
|  |   border-bottom: 1px solid #b8b8b8; | ||||||
|  | } | ||||||
|   | |||||||
| @@ -102,6 +102,14 @@ public class ChangeApi { | |||||||
|     call(id, commit, "cherrypick").post(cherryPickInput, cb); |     call(id, commit, "cherrypick").post(cherryPickInput, cb); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** Edit commit message for specific revision of a change. */ | ||||||
|  |   public static void message(int id, String commit, String message, | ||||||
|  |       AsyncCallback<JavaScriptObject> cb) { | ||||||
|  |     CherryPickInput input = CherryPickInput.create(); | ||||||
|  |     input.setMessage(message); | ||||||
|  |     call(id, commit, "message").post(input, cb); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   /** Submit a specific revision of a change. */ |   /** Submit a specific revision of a change. */ | ||||||
|   public static void submit(int id, String commit, AsyncCallback<SubmitInfo> cb) { |   public static void submit(int id, String commit, AsyncCallback<SubmitInfo> cb) { | ||||||
|     SubmitInput in = SubmitInput.create(); |     SubmitInput in = SubmitInput.create(); | ||||||
|   | |||||||
| @@ -58,6 +58,7 @@ public interface ChangeConstants extends Constants { | |||||||
|   String keyReload(); |   String keyReload(); | ||||||
|   String keyPublishComments(); |   String keyPublishComments(); | ||||||
|   String keyEditTopic(); |   String keyEditTopic(); | ||||||
|  |   String keyEditMessage(); | ||||||
|  |  | ||||||
|   String patchTableColumnName(); |   String patchTableColumnName(); | ||||||
|   String patchTableColumnComments(); |   String patchTableColumnComments(); | ||||||
|   | |||||||
| @@ -38,6 +38,8 @@ nextPatchSet = Next patch set | |||||||
| keyReload = Reload change | keyReload = Reload change | ||||||
| keyPublishComments = Review and publish comments | keyPublishComments = Review and publish comments | ||||||
| keyEditTopic = Edit change topic | keyEditTopic = Edit change topic | ||||||
|  | keyEditMessage = Edit commit message | ||||||
|  |  | ||||||
|  |  | ||||||
| patchTableColumnName = File Path | patchTableColumnName = File Path | ||||||
| patchTableColumnComments = Comments | patchTableColumnComments = Comments | ||||||
|   | |||||||
| @@ -0,0 +1,126 @@ | |||||||
|  | // 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.server.change; | ||||||
|  |  | ||||||
|  | import com.google.common.base.Strings; | ||||||
|  | import com.google.gerrit.common.errors.EmailException; | ||||||
|  | import com.google.gerrit.extensions.restapi.BadRequestException; | ||||||
|  | import com.google.gerrit.extensions.restapi.DefaultInput; | ||||||
|  | import com.google.gerrit.extensions.restapi.ResourceConflictException; | ||||||
|  | import com.google.gerrit.extensions.restapi.ResourceNotFoundException; | ||||||
|  | import com.google.gerrit.extensions.restapi.RestModifyView; | ||||||
|  | import com.google.gerrit.extensions.webui.UiAction; | ||||||
|  | import com.google.gerrit.reviewdb.client.PatchSet; | ||||||
|  | import com.google.gerrit.reviewdb.server.ReviewDb; | ||||||
|  | import com.google.gerrit.server.ChangeUtil; | ||||||
|  | import com.google.gerrit.server.GerritPersonIdent; | ||||||
|  | import com.google.gerrit.server.IdentifiedUser; | ||||||
|  | import com.google.gerrit.server.change.ChangeJson.ChangeInfo; | ||||||
|  | import com.google.gerrit.server.change.EditMessage.Input; | ||||||
|  | import com.google.gerrit.server.git.GitRepositoryManager; | ||||||
|  | import com.google.gerrit.server.mail.CommitMessageEditedSender; | ||||||
|  | import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException; | ||||||
|  | import com.google.gerrit.server.project.InvalidChangeOperationException; | ||||||
|  | import com.google.gerrit.server.project.NoSuchChangeException; | ||||||
|  | import com.google.gwtorm.server.OrmException; | ||||||
|  | import com.google.inject.Inject; | ||||||
|  | import com.google.inject.Provider; | ||||||
|  |  | ||||||
|  | import org.eclipse.jgit.errors.IncorrectObjectTypeException; | ||||||
|  | import org.eclipse.jgit.errors.MissingObjectException; | ||||||
|  | import org.eclipse.jgit.errors.RepositoryNotFoundException; | ||||||
|  | import org.eclipse.jgit.lib.PersonIdent; | ||||||
|  | import org.eclipse.jgit.lib.Repository; | ||||||
|  |  | ||||||
|  | import java.io.IOException; | ||||||
|  |  | ||||||
|  | class EditMessage implements RestModifyView<RevisionResource, Input>, | ||||||
|  |     UiAction<RevisionResource> { | ||||||
|  |  | ||||||
|  |   private final Provider<ReviewDb> dbProvider; | ||||||
|  |   private final CommitMessageEditedSender.Factory commitMessageEditedSenderFactory; | ||||||
|  |   private final GitRepositoryManager gitManager; | ||||||
|  |   private final PersonIdent myIdent; | ||||||
|  |   private final PatchSetInserter.Factory patchSetInserterFactory; | ||||||
|  |   private final ChangeJson json; | ||||||
|  |  | ||||||
|  |   static class Input { | ||||||
|  |     @DefaultInput | ||||||
|  |     String message; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Inject | ||||||
|  |   EditMessage(final Provider<ReviewDb> dbProvider, | ||||||
|  |       final CommitMessageEditedSender.Factory commitMessageEditedSenderFactory, | ||||||
|  |       final GitRepositoryManager gitManager, | ||||||
|  |       final PatchSetInserter.Factory patchSetInserterFactory, | ||||||
|  |       @GerritPersonIdent final PersonIdent myIdent, | ||||||
|  |       ChangeJson json) { | ||||||
|  |     this.dbProvider = dbProvider; | ||||||
|  |     this.commitMessageEditedSenderFactory = commitMessageEditedSenderFactory; | ||||||
|  |     this.gitManager = gitManager; | ||||||
|  |     this.myIdent = myIdent; | ||||||
|  |     this.patchSetInserterFactory = patchSetInserterFactory; | ||||||
|  |     this.json = json; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Override | ||||||
|  |   public ChangeInfo apply(RevisionResource rsrc, Input input) | ||||||
|  |       throws BadRequestException, ResourceConflictException, EmailException, | ||||||
|  |       OrmException, ResourceNotFoundException, IOException { | ||||||
|  |     if (Strings.isNullOrEmpty(input.message)) { | ||||||
|  |       throw new BadRequestException("message must be non-empty"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     final Repository git; | ||||||
|  |     try { | ||||||
|  |       git = gitManager.openRepository(rsrc.getChange().getProject()); | ||||||
|  |     } catch (RepositoryNotFoundException e) { | ||||||
|  |       throw new ResourceNotFoundException(e.getMessage()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     try { | ||||||
|  |       return json.format(ChangeUtil.editCommitMessage( | ||||||
|  |           rsrc.getPatchSet().getId(), | ||||||
|  |           rsrc.getControl().getRefControl(), | ||||||
|  |           (IdentifiedUser) rsrc.getControl().getCurrentUser(), | ||||||
|  |           input.message, dbProvider.get(), | ||||||
|  |           commitMessageEditedSenderFactory, git, myIdent, | ||||||
|  |           patchSetInserterFactory)); | ||||||
|  |     } catch (InvalidChangeOperationException e) { | ||||||
|  |       throw new BadRequestException(e.getMessage()); | ||||||
|  |     } catch (MissingObjectException e) { | ||||||
|  |       throw new ResourceConflictException(e.getMessage()); | ||||||
|  |     } catch (IncorrectObjectTypeException e) { | ||||||
|  |       throw new ResourceConflictException(e.getMessage()); | ||||||
|  |     } catch (PatchSetInfoNotAvailableException e) { | ||||||
|  |       throw new ResourceConflictException(e.getMessage()); | ||||||
|  |     } catch (NoSuchChangeException e) { | ||||||
|  |       throw new ResourceNotFoundException(); | ||||||
|  |     } finally { | ||||||
|  |       git.close(); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   @Override | ||||||
|  |   public UiAction.Description getDescription(RevisionResource resource) { | ||||||
|  |     PatchSet.Id current = resource.getChange().currentPatchSetId(); | ||||||
|  |     return new UiAction.Description() | ||||||
|  |         .setLabel("Edit commit message") | ||||||
|  |         .setVisible(resource.getChange().getStatus().isOpen() | ||||||
|  |             && resource.getPatchSet().getId().equals(current) | ||||||
|  |             && resource.getControl().canAddPatchSet()); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @@ -69,6 +69,7 @@ public class Module extends RestApiModule { | |||||||
|     post(REVISION_KIND, "review").to(PostReview.class); |     post(REVISION_KIND, "review").to(PostReview.class); | ||||||
|     post(REVISION_KIND, "submit").to(Submit.class); |     post(REVISION_KIND, "submit").to(Submit.class); | ||||||
|     post(REVISION_KIND, "rebase").to(Rebase.class); |     post(REVISION_KIND, "rebase").to(Rebase.class); | ||||||
|  |     post(REVISION_KIND, "message").to(EditMessage.class); | ||||||
|     get(REVISION_KIND, "patch").to(GetPatch.class); |     get(REVISION_KIND, "patch").to(GetPatch.class); | ||||||
|     get(REVISION_KIND, "submit_type").to(TestSubmitType.Get.class); |     get(REVISION_KIND, "submit_type").to(TestSubmitType.Get.class); | ||||||
|     post(REVISION_KIND, "test.submit_rule").to(TestSubmitRule.class); |     post(REVISION_KIND, "test.submit_rule").to(TestSubmitRule.class); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user