/*******************************************************************************
* 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) {
}
}