/******************************************************************************* * Copyright (c) 2006 Red Hat Inc. 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: * Kyu Lee <klee@redhat.com> - initial API and implementation *******************************************************************************/ package org.eclipse.linuxtools.internal.changelog.core.actions; import java.io.IOException; import java.io.InputStreamReader; import java.io.LineNumberReader; import java.io.UnsupportedEncodingException; import java.lang.reflect.InvocationTargetException; import org.eclipse.compare.rangedifferencer.RangeDifference; import org.eclipse.compare.rangedifferencer.RangeDifferencer; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.IHandler; import org.eclipse.core.commands.IHandlerListener; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IStorage; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.ProgressMonitorDialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.linuxtools.internal.changelog.core.ChangelogPlugin; import org.eclipse.linuxtools.internal.changelog.core.LineComparator; import org.eclipse.linuxtools.internal.changelog.core.Messages; import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.team.core.RepositoryProvider; import org.eclipse.team.core.TeamException; import org.eclipse.team.core.diff.IDiff; import org.eclipse.team.core.diff.IThreeWayDiff; import org.eclipse.team.core.history.IFileRevision; import org.eclipse.team.core.mapping.IResourceDiff; import org.eclipse.team.core.subscribers.Subscriber; import org.eclipse.team.core.synchronize.SyncInfo; import org.eclipse.team.core.synchronize.SyncInfoSet; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.PlatformUI; public class PrepareCommitHandler extends ChangeLogAction implements IHandler { @Override public Object execute(ExecutionEvent event) { IRunnableWithProgress code = monitor -> loadClipboard(monitor); ProgressMonitorDialog pd = new ProgressMonitorDialog(PlatformUI .getWorkbench().getActiveWorkbenchWindow().getShell()); try { pd.run(false /* fork */, false /* cancelable */, code); } catch (InvocationTargetException e) { ChangelogPlugin .getDefault() .getLog() .log(new Status(IStatus.ERROR, ChangelogPlugin.PLUGIN_ID, IStatus.ERROR, e.getMessage(), e)); } catch (InterruptedException e) { ChangelogPlugin .getDefault() .getLog() .log(new Status(IStatus.ERROR, ChangelogPlugin.PLUGIN_ID, IStatus.ERROR, e.getMessage(), e)); } return null; } private void loadClipboard(IProgressMonitor monitor) { IEditorPart currentEditor; try { currentEditor = PlatformUI.getWorkbench() .getActiveWorkbenchWindow().getActivePage() .getActiveEditor(); } catch (Exception e) { // no editor is active now so do nothing return; } if (currentEditor == null) { return; } IFile changelog = getChangelogFile(getDocumentLocation(currentEditor, false)); if (changelog == null) { return; } String diffResult = ""; IProject project = null; IResource[] resources = new IResource[] { changelog }; project = changelog.getProject(); RepositoryProvider r = RepositoryProvider.getProvider(project); if (r == null) { return; // There is no repository provider for this project, i.e // it's not shared. } SyncInfoSet set = new SyncInfoSet(); Subscriber s = r.getSubscriber(); try { s.refresh(resources, IResource.DEPTH_ZERO, monitor); } catch (TeamException e1) { // Ignore, continue anyways } s.collectOutOfSync(resources, IResource.DEPTH_ZERO, set, monitor); SyncInfo[] infos = set.getSyncInfos(); if (infos.length == 1) { int kind = SyncInfo.getChange(infos[0].getKind()); if (kind == SyncInfo.CHANGE) { try { IDiff d = s.getDiff(infos[0].getLocal()); if (d instanceof IThreeWayDiff && ((IThreeWayDiff) d).getDirection() == IThreeWayDiff.OUTGOING) { IThreeWayDiff diff = (IThreeWayDiff) d; monitor.beginTask(null, 100); IResourceDiff localDiff = (IResourceDiff) diff .getLocalChange(); IFile file = (IFile) localDiff.getResource(); monitor.subTask(Messages .getString("ChangeLog.MergingDiffs")); // $NON-NLS-1$ String osEncoding = file.getCharset(); IFileRevision ancestorState = localDiff .getBeforeState(); IStorage ancestorStorage; if (ancestorState != null) ancestorStorage = ancestorState.getStorage(monitor); else { ancestorStorage = null; return; } try { LineComparator left = new LineComparator( ancestorStorage.getContents(), osEncoding); LineComparator right = new LineComparator( file.getContents(), osEncoding); for (RangeDifference tmp : RangeDifferencer .findDifferences(left, right)) { if (tmp.kind() == RangeDifference.CHANGE) { LineNumberReader l = new LineNumberReader( new InputStreamReader( file.getContents())); int rightLength = tmp.rightLength() > 0 ? tmp .rightLength() : tmp.rightLength() + 1; String line0 = null; String preDiffResult = ""; for (int i = 0; i < tmp.rightStart(); ++i) { // We have equivalence at the start. // This could be due to a new entry with // the // same date stamp as the subsequent // entry. In this case, we want the diff // to // have the date stamp at the top so it // forms a complete entry. So, we cache // those equivalent lines for later // usage if needed. try { String line = l.readLine(); if (line0 == null) line0 = line; preDiffResult += line + "\n"; } catch (IOException e) { break; } } for (int i = 0; i < rightLength; ++i) { try { String line = l.readLine(); // If the last line of the diff // matches the first line of the old // file and // there was equivalence at the // start of the ChangeLog, then we // want to put // the equivalent section at top so // as to give the best chance of // forming // a ChangeLog entry that can be // used as a commit comment. if (i == rightLength - tmp.rightStart()) { if (tmp.rightStart() != 0 && line.equals(line0)) { diffResult = preDiffResult += diffResult; i = rightLength; // stop // loop } else diffResult += line + "\n"; } else diffResult += line + "\n"; // $NON-NLS-1$ } catch (IOException e) { // do nothing } } } } } catch (UnsupportedEncodingException e) { // do nothing for now } monitor.done(); } } catch (CoreException e) { // do nothing } } } if (!diffResult.equals("")) populateClipboardBuffer(diffResult); } private void populateClipboardBuffer(String input) { TextTransfer plainTextTransfer = TextTransfer.getInstance(); Clipboard clipboard = new Clipboard(PlatformUI.getWorkbench() .getDisplay()); clipboard.setContents(new String[] { input }, new Transfer[] { plainTextTransfer }); clipboard.dispose(); } @Override public void addHandlerListener(IHandlerListener handlerListener) { } @Override public void dispose() { } @Override public void removeHandlerListener(IHandlerListener handlerListener) { } }