352377: add command to copy commit message to clipboard

Change-Id: Ie17152f32284ea5086c72dd159b7d135cc350d42
Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=352377
diff --git a/org.eclipse.mylyn.team.tests/src/org/eclipse/mylyn/team/tests/AllTeamTests.java b/org.eclipse.mylyn.team.tests/src/org/eclipse/mylyn/team/tests/AllTeamTests.java
index 34383cb..712f6b8 100644
--- a/org.eclipse.mylyn.team.tests/src/org/eclipse/mylyn/team/tests/AllTeamTests.java
+++ b/org.eclipse.mylyn.team.tests/src/org/eclipse/mylyn/team/tests/AllTeamTests.java
@@ -11,11 +11,11 @@
 
 package org.eclipse.mylyn.team.tests;
 
+import org.eclipse.mylyn.context.sdk.util.ContextTestUtil;
+
 import junit.framework.Test;
 import junit.framework.TestSuite;
 
-import org.eclipse.mylyn.context.sdk.util.ContextTestUtil;
-
 /**
  * @author Mik Kersten
  */
@@ -31,6 +31,7 @@
 		suite.addTestSuite(TeamPropertiesLinkProviderTest.class);
 		suite.addTestSuite(TaskFinderTest.class);
 		suite.addTestSuite(CommitTemplateVariablesTest.class);
+		suite.addTestSuite(CopyCommitMessageHandlerTest.class);
 		return suite;
 	}
 
diff --git a/org.eclipse.mylyn.team.tests/src/org/eclipse/mylyn/team/tests/CopyCommitMessageHandlerTest.java b/org.eclipse.mylyn.team.tests/src/org/eclipse/mylyn/team/tests/CopyCommitMessageHandlerTest.java
new file mode 100644
index 0000000..270cd8f
--- /dev/null
+++ b/org.eclipse.mylyn.team.tests/src/org/eclipse/mylyn/team/tests/CopyCommitMessageHandlerTest.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Tasktop Technologies and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Tasktop Technologies - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylyn.team.tests;
+
+import org.eclipse.core.commands.Command;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin;
+import org.eclipse.mylyn.internal.team.ui.FocusedTeamUiPlugin;
+import org.eclipse.mylyn.tasks.core.ITask;
+import org.eclipse.mylyn.tasks.core.TaskRepository;
+import org.eclipse.mylyn.tasks.tests.TaskTestUtil;
+import org.eclipse.mylyn.tasks.tests.connector.MockRepositoryConnector;
+import org.eclipse.mylyn.tasks.ui.TasksUi;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.commands.ICommandService;
+import org.eclipse.ui.handlers.IHandlerService;
+import org.junit.Test;
+
+import junit.framework.TestCase;
+
+public class CopyCommitMessageHandlerTest extends TestCase {
+
+	private Clipboard clipboard;
+
+	private TaskRepository repository;
+
+	@Override
+	protected void setUp() throws Exception {
+		TaskTestUtil.resetTaskListAndRepositories();
+
+		repository = new TaskRepository(MockRepositoryConnector.CONNECTOR_KIND, MockRepositoryConnector.REPOSITORY_URL);
+		TasksUiPlugin.getRepositoryManager().addRepository(repository);
+
+		Display display = PlatformUI.getWorkbench().getDisplay();
+		clipboard = new Clipboard(display);
+
+		FocusedTeamUiPlugin.getDefault().getPreferenceStore().setToDefault(FocusedTeamUiPlugin.COMMIT_TEMPLATE);
+	}
+
+	@Override
+	protected void tearDown() throws Exception {
+		clipboard.dispose();
+
+		TaskTestUtil.resetTaskListAndRepositories();
+	}
+
+	@Test
+	public void testCopyCommitMessage() throws Exception {
+		String contents = getClipboardContents();
+
+		executeCommand();
+		assertEquals(contents, getClipboardContents());
+
+		addAndSelectTask();
+		executeCommand();
+		assertEquals("1: My Task \n\nTask-Url: http://url", getClipboardContents());
+	}
+
+	private void addAndSelectTask() throws Exception {
+		ITask task = TasksUi.getRepositoryModel().createTask(repository, "1");
+		task.setTaskKey("1");
+		task.setSummary("My Task");
+		task.setUrl("http://url");
+		TaskTestUtil.addAndSelectTask(task);
+	}
+
+	private String getClipboardContents() {
+		TextTransfer textTransfer = TextTransfer.getInstance();
+		return (String) clipboard.getContents(textTransfer);
+	}
+
+	public void executeCommand() throws Exception {
+		ICommandService commandService = PlatformUI.getWorkbench().getService(ICommandService.class);
+		Command command = commandService.getCommand("org.eclipse.mylyn.team.ui.commands.CopyCommitMessage");
+
+		IHandlerService handlerService = PlatformUI.getWorkbench().getService(IHandlerService.class);
+		ExecutionEvent event = handlerService.createExecutionEvent(command, null);
+		command.executeWithChecks(event);
+	}
+
+}
diff --git a/org.eclipse.mylyn.team.ui/plugin.xml b/org.eclipse.mylyn.team.ui/plugin.xml
index a5c2cde..8a16284 100644
--- a/org.eclipse.mylyn.team.ui/plugin.xml
+++ b/org.eclipse.mylyn.team.ui/plugin.xml
@@ -327,5 +327,27 @@
             id="org.eclipse.mylyn.team.ui.TaskFinderUrlHandler">
       </handler>
    </extension>
+   <extension
+         point="org.eclipse.ui.commands">
+      <command
+            categoryId="org.eclipse.mylyn.tasks.ui.commands"
+            defaultHandler="org.eclipse.mylyn.internal.team.ui.commands.CopyCommitMessageHandler"
+            description="Copies a commit message for the currently selected task to the clipboard."
+            id="org.eclipse.mylyn.team.ui.commands.CopyCommitMessage"
+            name="Copy Commit Message for Task">
+      </command>
+   </extension>
+   <extension
+         point="org.eclipse.ui.menus">
+      <menuContribution
+            allPopups="false"
+            locationURI="menu:org.eclipse.mylyn.tasklist.actions.copy?after=additions">
+         <command
+               commandId="org.eclipse.mylyn.team.ui.commands.CopyCommitMessage"
+               label="Commit Message"
+               style="push">
+         </command>
+      </menuContribution>
+   </extension>
 	
 </plugin>
diff --git a/org.eclipse.mylyn.team.ui/src/org/eclipse/mylyn/internal/team/ui/commands/CopyCommitMessageHandler.java b/org.eclipse.mylyn.team.ui/src/org/eclipse/mylyn/internal/team/ui/commands/CopyCommitMessageHandler.java
new file mode 100644
index 0000000..b8eb715
--- /dev/null
+++ b/org.eclipse.mylyn.team.ui/src/org/eclipse/mylyn/internal/team/ui/commands/CopyCommitMessageHandler.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Tasktop Technologies and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Tasktop Technologies - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.mylyn.internal.team.ui.commands;
+
+import java.util.Optional;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.mylyn.commons.ui.ClipboardCopier;
+import org.eclipse.mylyn.tasks.core.ITask;
+import org.eclipse.mylyn.team.ui.TeamUiUtil;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+public class CopyCommitMessageHandler extends AbstractHandler {
+
+	@Override
+	public Object execute(ExecutionEvent event) throws ExecutionException {
+		ISelection selection = HandlerUtil.getActiveMenuSelection(event);
+		if (selection == null) {
+			selection = HandlerUtil.getCurrentSelection(event);
+		}
+		Optional<ITask> task = getTask(selection);
+		if (task.isPresent()) {
+			String comment = TeamUiUtil.getComment(false, task.get(), null);
+			ClipboardCopier.getDefault().copy(comment);
+		}
+		return null;
+	}
+
+	private Optional<ITask> getTask(ISelection selection) {
+		if (selection instanceof StructuredSelection) {
+			StructuredSelection structuredSelection = (StructuredSelection) selection;
+			if (structuredSelection.getFirstElement() instanceof ITask) {
+				return Optional.of((ITask) structuredSelection.getFirstElement());
+			}
+		}
+		return Optional.empty();
+	}
+
+}