/*******************************************************************************
* Copyright (C) 2015, Max Hohenegger <eclipse@hohenegger.eu>
*
* 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
*******************************************************************************/
package org.eclipse.egit.gitflow.ui.internal.actions;
import static org.eclipse.egit.gitflow.ui.Activator.error;
import java.io.IOException;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.egit.core.internal.job.JobUtil;
import org.eclipse.egit.core.op.CommitOperation;
import org.eclipse.egit.gitflow.GitFlowRepository;
import org.eclipse.egit.gitflow.WrongGitFlowStateException;
import org.eclipse.egit.gitflow.op.FeatureFinishOperation;
import org.eclipse.egit.gitflow.ui.Activator;
import org.eclipse.egit.gitflow.ui.internal.JobFamilies;
import org.eclipse.egit.gitflow.ui.internal.UIText;
import org.eclipse.egit.gitflow.ui.internal.dialogs.FinishFeatureDialog;
import org.eclipse.egit.ui.internal.UIRepositoryUtils;
import org.eclipse.egit.ui.internal.commit.CommitHelper;
import org.eclipse.egit.ui.internal.rebase.CommitMessageEditorDialog;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.window.Window;
import org.eclipse.jgit.api.MergeResult;
import org.eclipse.jgit.api.MergeResult.MergeStatus;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.handlers.HandlerUtil;
/**
* git flow feature finish
*/
public class FeatureFinishHandler extends AbstractGitFlowHandler {
@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
final GitFlowRepository gfRepo = GitFlowHandlerUtil.getRepository(event);
if (gfRepo == null) {
return error(UIText.Handlers_noGitflowRepositoryFound);
}
final String featureBranch;
Repository repo = gfRepo.getRepository();
try {
featureBranch = repo.getBranch();
} catch (IOException e) {
return error(e.getMessage(), e);
}
Shell activeShell = HandlerUtil.getActiveShell(event);
FinishFeatureDialog dialog = new FinishFeatureDialog(activeShell,
featureBranch);
if (dialog.open() != Window.OK) {
return null;
}
final boolean squash = dialog.isSquash();
boolean keepBranch = dialog.isKeepBranch();
try {
try {
if (squash && !UIRepositoryUtils.handleUncommittedFiles(repo, activeShell))
return null;
} catch (GitAPIException e) {
Activator.logError(e.getMessage(), e);
return null;
}
final FeatureFinishOperation operation = new FeatureFinishOperation(
gfRepo);
operation.setSquash(squash);
operation.setKeepBranch(keepBranch);
JobUtil.scheduleUserWorkspaceJob(operation,
UIText.FeatureFinishHandler_finishingFeature,
JobFamilies.GITFLOW_FAMILY, new JobChangeAdapter() {
@Override
public void done(IJobChangeEvent jobChangeEvent) {
if (jobChangeEvent.getResult().isOK()) {
postMerge(gfRepo, featureBranch, squash,
operation.getMergeResult());
}
}
});
} catch (WrongGitFlowStateException | CoreException | IOException
| OperationCanceledException e) {
return error(e.getMessage(), e);
}
return null;
}
private void postMerge(final GitFlowRepository gfRepo,
final String featureBranch, final boolean squash,
final MergeResult mergeResult) {
Display display = Display.getDefault();
display.asyncExec(new Runnable() {
@Override
public void run() {
Shell activeShell = Display.getDefault().getActiveShell();
if (squash && mergeResult.getMergedCommits().length > 1) {
try {
rewordCommitMessage(activeShell, gfRepo);
} catch (CoreException | IOException e) {
throw new RuntimeException(e);
}
}
MergeStatus mergeStatus = mergeResult.getMergeStatus();
if (MergeStatus.CONFLICTING.equals(mergeStatus)) {
String develop = gfRepo.getConfig().getDevelop();
MultiStatus status = createMergeConflictInfo(develop,
featureBranch, mergeResult);
ErrorDialog.openError(null, UIText.FeatureFinishHandler_Conflicts,
null, status);
}
}
});
}
private void rewordCommitMessage(Shell activeShell,
final GitFlowRepository gfRepo) throws CoreException, IOException {
Repository repository = gfRepo.getRepository();
CommitHelper commitHelper = new CommitHelper(repository);
CommitMessageEditorDialog messageEditorDialog = new CommitMessageEditorDialog(
activeShell, repository.readSquashCommitMsg(),
UIText.FeatureFinishHandler_rewordSquashedCommitMessage);
if (Window.OK == messageEditorDialog.open()) {
String commitMessage = stripCommentLines(messageEditorDialog
.getCommitMessage());
CommitOperation commitOperation = new CommitOperation(repository,
commitHelper.getAuthor(), commitHelper.getCommitter(),
commitMessage);
commitOperation.execute(null);
}
}
private static String stripCommentLines(String commitMessage) {
StringBuilder result = new StringBuilder();
for (String line : commitMessage.split("\n")) { //$NON-NLS-1$
if (!line.trim().startsWith("#")) //$NON-NLS-1$
result.append(line).append("\n"); //$NON-NLS-1$
}
if (!commitMessage.endsWith("\n")) //$NON-NLS-1$
result.deleteCharAt(result.length() - 1);
return result.toString();
}
}