diff options
| author | Markus Duft | 2012-03-22 07:03:58 +0000 |
|---|---|---|
| committer | Robin Rosenberg | 2013-01-20 21:04:20 +0000 |
| commit | 33555cc3d65392fd95e9d934f68fcf4b89eeddbf (patch) | |
| tree | 5733e8970bbbf2a60da93883698b77ff609e6062 | |
| parent | a30cf4b21a5e6f80f49454c12add8bfa9b5daf07 (diff) | |
| download | egit-33555cc3d65392fd95e9d934f68fcf4b89eeddbf.tar.gz egit-33555cc3d65392fd95e9d934f68fcf4b89eeddbf.tar.xz egit-33555cc3d65392fd95e9d934f68fcf4b89eeddbf.zip | |
Properly handle checkout conflict exceptions
Properly handle a possible checkout conflict exception and display
a suiting dialog to the user also when merging and rebasing.
JGit-Dependency: I48d9bdcc1e98095576513a54a225a42409f301f3
Change-Id: I23780261308a6ce614355e724e7dbf0dfb4d35a7
Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
10 files changed, 189 insertions, 47 deletions
diff --git a/org.eclipse.egit.core/src/org/eclipse/egit/core/op/MergeOperation.java b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/MergeOperation.java index 045818b98d..0a60886925 100644 --- a/org.eclipse.egit.core/src/org/eclipse/egit/core/op/MergeOperation.java +++ b/org.eclipse.egit.core/src/org/eclipse/egit/core/op/MergeOperation.java @@ -14,7 +14,6 @@ package org.eclipse.egit.core.op; import java.io.IOException; -import java.text.MessageFormat; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IWorkspaceRunnable; @@ -129,17 +128,8 @@ public class MergeOperation implements IEGitOperation { } catch (ConcurrentRefUpdateException e) { throw new TeamException(CoreText.MergeOperation_MergeFailedRefUpdate, e); } catch (CheckoutConflictException e) { - StringBuilder builder = new StringBuilder(); - for (String f : e.getConflictingPaths()) { - builder.append("\n"); //$NON-NLS-1$ - builder.append(f); - } - throw new TeamException( - new Status( - IStatus.INFO, - Activator.getPluginId(), - MessageFormat.format(CoreText.MergeOperation_CheckoutConflict, - builder.toString()))); + mergeResult = new MergeResult(e.getConflictingPaths()); + return; } catch (GitAPIException e) { throw new TeamException(e.getLocalizedMessage(), e.getCause()); } finally { diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java index 0d502b6421..055e95b76f 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/UIText.java @@ -903,6 +903,9 @@ public class UIText extends NLS { public static String ClearCredentialsCommand_clearingCredentialsFailed; /** */ + public static String CheckoutConflictDialog_conflictMessage; + + /** */ public static String CheckoutDialog_Message; /** */ diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/MergeActionHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/MergeActionHandler.java index ee5abe65e9..0155168217 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/MergeActionHandler.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/actions/MergeActionHandler.java @@ -97,7 +97,7 @@ public class MergeActionHandler extends RepositoryActionHandler { public void run() { Shell shell = PlatformUI.getWorkbench() .getActiveWorkbenchWindow().getShell(); - new MergeResultDialog(shell, repository, op + MergeResultDialog.getDialog(shell, repository, op .getResult()).open(); } }); diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/CheckoutConflictDialog.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/CheckoutConflictDialog.java new file mode 100644 index 0000000000..3915a33d4b --- /dev/null +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/dialogs/CheckoutConflictDialog.java @@ -0,0 +1,102 @@ +/******************************************************************************* + * Copyright (C) 2011, Mathias Kinzler <mathias.kinzler@sap.com> + * and other copyright owners as documented in the project's IP log. + * + * 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: + * Markus Duft - Refactoring from RebaseResultDialog + *******************************************************************************/ +package org.eclipse.egit.ui.internal.dialogs; + +import java.util.List; + +import org.eclipse.egit.ui.UIText; +import org.eclipse.egit.ui.internal.CommonUtils; +import org.eclipse.egit.ui.internal.repository.tree.RepositoryNode; +import org.eclipse.egit.ui.internal.repository.tree.command.CommitCommand; +import org.eclipse.egit.ui.internal.repository.tree.command.ResetCommand; +import org.eclipse.egit.ui.internal.repository.tree.command.StashCreateCommand; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.PlatformUI; + +/** + * Display a checkout conflict + */ +public class CheckoutConflictDialog extends MessageDialog { + private static final Image INFO = PlatformUI.getWorkbench() + .getSharedImages().getImage(ISharedImages.IMG_OBJS_INFO_TSK); + private List<String> conflicts; + private Repository repository; + + /** + * @param shell + * @param repository + * @param conflicts + */ + public CheckoutConflictDialog(Shell shell, Repository repository, List<String> conflicts) { + super(shell, UIText.BranchResultDialog_CheckoutConflictsTitle, INFO, + UIText.CheckoutConflictDialog_conflictMessage, + MessageDialog.INFORMATION, + new String[] { IDialogConstants.OK_LABEL }, 0); + setShellStyle(getShellStyle() | SWT.SHELL_TRIM); + this.repository = repository; + this.conflicts = conflicts; + } + + @Override + protected Control createCustomArea(Composite parent) { + Composite main = new Composite(parent, SWT.NONE); + main.setLayout(new GridLayout(1, false)); + GridDataFactory.fillDefaults().indent(0, 0).grab(true, true) + .applyTo(main); + new NonDeletedFilesTree(main, repository, this.conflicts); + applyDialogFont(main); + + return main; + } + + protected void buttonPressed(int buttonId) { + switch (buttonId) { + case IDialogConstants.PROCEED_ID: + CommonUtils.runCommand(CommitCommand.ID, new StructuredSelection( + new RepositoryNode(null, repository))); + break; + case IDialogConstants.ABORT_ID: + CommonUtils.runCommand(ResetCommand.ID, new StructuredSelection( + new RepositoryNode(null, repository))); + break; + case IDialogConstants.SKIP_ID: + CommonUtils.runCommand(StashCreateCommand.ID, + new StructuredSelection( + new RepositoryNode(null, repository))); + break; + } + super.buttonPressed(buttonId); + } + + @Override + protected void createButtonsForButtonBar(Composite parent) { + super.createButtonsForButtonBar(parent); + createButton(parent, IDialogConstants.ABORT_ID, + UIText.BranchResultDialog_buttonReset, false); + createButton(parent, IDialogConstants.PROCEED_ID, + UIText.BranchResultDialog_buttonCommit, false); + createButton(parent, IDialogConstants.SKIP_ID, + UIText.BranchResultDialog_buttonStash, false); + } +} diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/fetch/FetchGerritChangePage.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/fetch/FetchGerritChangePage.java index db6938d9f7..a75ecbbdc2 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/fetch/FetchGerritChangePage.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/fetch/FetchGerritChangePage.java @@ -32,6 +32,7 @@ import org.eclipse.egit.ui.UIPreferences; import org.eclipse.egit.ui.UIText; import org.eclipse.egit.ui.UIUtils; import org.eclipse.egit.ui.internal.branch.BranchOperationUI; +import org.eclipse.egit.ui.internal.dialogs.CheckoutConflictDialog; import org.eclipse.jface.bindings.keys.KeyStroke; import org.eclipse.jface.bindings.keys.ParseException; import org.eclipse.jface.dialogs.Dialog; @@ -43,7 +44,11 @@ import org.eclipse.jface.fieldassist.TextContentAdapter; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.jgit.api.CheckoutCommand; +import org.eclipse.jgit.api.CheckoutResult; +import org.eclipse.jgit.api.CheckoutResult.Status; import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.errors.CheckoutConflictException; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.PersonIdent; import org.eclipse.jgit.lib.Ref; @@ -70,6 +75,7 @@ import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; /** @@ -528,8 +534,30 @@ public class FetchGerritChangePage extends WizardPage { CreateLocalBranchOperation bop = new CreateLocalBranchOperation( repository, textForBranch, commit); bop.execute(monitor); - new Git(repository).checkout() - .setName(textForBranch).call(); + CheckoutCommand co = new Git(repository) + .checkout(); + try { + co.setName(textForBranch).call(); + } catch (CheckoutConflictException e) { + final CheckoutResult result = co + .getResult(); + + if (result.getStatus() == Status.CONFLICTS) { + final Shell shell = getWizard() + .getContainer().getShell(); + + shell.getDisplay().asyncExec( + new Runnable() { + public void run() { + new CheckoutConflictDialog( + shell, + repository, + result.getConflictList()) + .open(); + } + }); + } + } monitor.worked(1); } if (doCheckout || doCreateTag) { @@ -596,9 +624,8 @@ public class FetchGerritChangePage extends WizardPage { String patternString = contents; // ignore spaces in the beginning while (patternString.length() > 0 - && patternString.charAt(0) == ' ') { + && patternString.charAt(0) == ' ') patternString = patternString.substring(1); - } // we quote the string as it may contain spaces // and other stuff colliding with the Pattern @@ -607,9 +634,8 @@ public class FetchGerritChangePage extends WizardPage { patternString = patternString.replaceAll("\\x2A", ".*"); //$NON-NLS-1$ //$NON-NLS-2$ // make sure we add a (logical) * at the end - if (!patternString.endsWith(".*")) { //$NON-NLS-1$ + if (!patternString.endsWith(".*")) //$NON-NLS-1$ patternString = patternString + ".*"; //$NON-NLS-1$ - } // let's compile a case-insensitive pattern (assumes ASCII only) Pattern pattern; diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/command/MergeHandler.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/command/MergeHandler.java index 5375553730..adba9c90e2 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/command/MergeHandler.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/history/command/MergeHandler.java @@ -69,9 +69,9 @@ public class MergeHandler extends AbstractHistoryCommandHandler { HandlerUtil.getActiveShellChecked(event), nodes, UIText.MergeHandler_SelectBranchTitle, UIText.MergeHandler_SelectBranchMessage, SWT.SINGLE); - if (dlg.open() == Window.OK) { + if (dlg.open() == Window.OK) refName = dlg.getSelectedNode().getObject().getName(); - } else + else return null; } String jobname = NLS.bind(UIText.MergeAction_JobNameMerge, refName); @@ -93,7 +93,7 @@ public class MergeHandler extends AbstractHistoryCommandHandler { @Override public void done(IJobChangeEvent cevent) { IStatus result = cevent.getJob().getResult(); - if (result.getSeverity() == IStatus.CANCEL) { + if (result.getSeverity() == IStatus.CANCEL) Display.getDefault().asyncExec(new Runnable() { public void run() { // don't use getShell(event) here since @@ -108,19 +108,18 @@ public class MergeHandler extends AbstractHistoryCommandHandler { UIText.MergeAction_MergeCanceledMessage); } }); - } else if (!result.isOK()) { + else if (!result.isOK()) Activator.handleError(result.getMessage(), result .getException(), true); - } else { + else Display.getDefault().asyncExec(new Runnable() { public void run() { Shell shell = PlatformUI.getWorkbench() .getActiveWorkbenchWindow().getShell(); - new MergeResultDialog(shell, repository, op + MergeResultDialog.getDialog(shell, repository, op .getResult()).open(); } }); - } } }); job.schedule(); @@ -146,9 +145,8 @@ public class MergeHandler extends AbstractHistoryCommandHandler { ex = e; } - if (message != null) { + if (message != null) Activator.handleError(UIText.MergeAction_CannotMerge, ex, true); - } return (message == null); } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/merge/MergeResultDialog.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/merge/MergeResultDialog.java index 8006127992..8962df1617 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/merge/MergeResultDialog.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/merge/MergeResultDialog.java @@ -20,6 +20,7 @@ import org.eclipse.egit.ui.UIText; import org.eclipse.egit.ui.UIUtils; import org.eclipse.egit.ui.internal.commit.CommitEditor; import org.eclipse.egit.ui.internal.commit.RepositoryCommit; +import org.eclipse.egit.ui.internal.dialogs.CheckoutConflictDialog; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.IDialogSettings; @@ -75,6 +76,19 @@ public class MergeResultDialog extends Dialog { * @param parentShell * @param repository * @param mergeResult + * @return the created dialog + */ + public static Dialog getDialog(Shell parentShell, Repository repository, MergeResult mergeResult) { + if(mergeResult.getMergeStatus() == MergeStatus.CHECKOUT_CONFLICT) + return new CheckoutConflictDialog(parentShell, repository, mergeResult.getCheckoutConflicts()); + else + return new MergeResultDialog(parentShell, repository, mergeResult); + } + + /** + * @param parentShell + * @param repository + * @param mergeResult */ public MergeResultDialog(Shell parentShell, Repository repository, MergeResult mergeResult) { diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/rebase/RebaseResultDialog.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/rebase/RebaseResultDialog.java index 07c871025c..714ed98172 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/rebase/RebaseResultDialog.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/rebase/RebaseResultDialog.java @@ -33,6 +33,7 @@ import org.eclipse.egit.core.project.RepositoryMapping; import org.eclipse.egit.ui.Activator; import org.eclipse.egit.ui.UIPreferences; import org.eclipse.egit.ui.UIText; +import org.eclipse.egit.ui.internal.dialogs.CheckoutConflictDialog; import org.eclipse.egit.ui.internal.merge.GitMergeEditorInput; import org.eclipse.egit.ui.internal.merge.MergeModeDialog; import org.eclipse.jface.dialogs.IDialogConstants; @@ -103,6 +104,19 @@ public class RebaseResultDialog extends MessageDialog { boolean shouldShow = result.getStatus() == Status.STOPPED || Activator.getDefault().getPreferenceStore().getBoolean( UIPreferences.SHOW_REBASE_CONFIRM); + + if(result.getStatus() == Status.CONFLICTS) { + PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { + public void run() { + Shell shell = PlatformUI.getWorkbench() + .getActiveWorkbenchWindow().getShell(); + new CheckoutConflictDialog(shell, repository, result.getConflicts()).open(); + } + }); + + return; + } + if (!shouldShow) { Activator.getDefault().getLog().log( new org.eclipse.core.runtime.Status(IStatus.INFO, Activator @@ -198,10 +212,9 @@ public class RebaseResultDialog extends MessageDialog { commitMessage.getTextWidget().setText(commit.getFullMessage()); commitId.setText(commit.name()); dc = repo.lockDirCache(); - for (int i = 0; i < dc.getEntryCount(); i++) { + for (int i = 0; i < dc.getEntryCount(); i++) if (dc.getEntry(i).getStage() > 0) conflictPaths.add(dc.getEntry(i).getPathString()); - } if (conflictPaths.size() > 0) { message = NLS.bind(UIText.RebaseResultDialog_Conflicting, Integer.valueOf(conflictPaths.size())); @@ -287,12 +300,11 @@ public class RebaseResultDialog extends MessageDialog { startMergeButton.addSelectionListener(new SelectionListener() { public void widgetSelected(SelectionEvent e) { - if (startMergeButton.getSelection()) { + if (startMergeButton.getSelection()) nextSteps .getTextWidget() .setText( UIText.RebaseResultDialog_NextStepsAfterResolveConflicts); - } } public void widgetDefaultSelected(SelectionEvent e) { @@ -409,14 +421,13 @@ public class RebaseResultDialog extends MessageDialog { IPath repoWorkdirPath = new Path(repo.getWorkTree().getPath()); for (String repoPath : conflictPaths) { IPath filePath = repoWorkdirPath.append(repoPath); - for (IProject project : validProjects) { + for (IProject project : validProjects) if (project.getLocation().isPrefixOf(filePath)) { IResource res = project.getFile(filePath .removeFirstSegments(project.getLocation() .segmentCount())); resourceList.add(res); } - } } IResource[] resources = new IResource[resourceList.size()]; resourceList.toArray(resources); @@ -435,7 +446,7 @@ public class RebaseResultDialog extends MessageDialog { } CompareUI.openCompareEditor(input); return; - } else if (skipCommitButton.getSelection()) { + } else if (skipCommitButton.getSelection()) // skip the rebase try { final RebaseOperation op = new RebaseOperation(repo, @@ -446,7 +457,7 @@ public class RebaseResultDialog extends MessageDialog { } catch (CoreException e) { Activator.handleError(e.getMessage(), e, true); } - } else if (abortRebaseButton.getSelection()) { + else if (abortRebaseButton.getSelection()) // abort the rebase try { final RebaseOperation op = new RebaseOperation(repo, @@ -457,7 +468,7 @@ public class RebaseResultDialog extends MessageDialog { } catch (CoreException e) { Activator.handleError(e.getMessage(), e, true); } - } else if (doNothingButton.getSelection()) { + else if (doNothingButton.getSelection()) { // nothing } } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/tree/command/MergeCommand.java b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/tree/command/MergeCommand.java index 7de246cada..a06c715e72 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/tree/command/MergeCommand.java +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/internal/repository/tree/command/MergeCommand.java @@ -80,11 +80,10 @@ public class MergeCommand extends else { MergeTargetSelectionDialog mergeTargetSelectionDialog = new MergeTargetSelectionDialog( getShell(event), repository); - if (mergeTargetSelectionDialog.open() == IDialogConstants.OK_ID) { + if (mergeTargetSelectionDialog.open() == IDialogConstants.OK_ID) refName = mergeTargetSelectionDialog.getRefName(); - } else { + else return null; - } } String jobname = NLS.bind(UIText.MergeAction_JobNameMerge, refName); @@ -106,7 +105,7 @@ public class MergeCommand extends @Override public void done(IJobChangeEvent jobEvent) { IStatus result = jobEvent.getJob().getResult(); - if (result.getSeverity() == IStatus.CANCEL) { + if (result.getSeverity() == IStatus.CANCEL) Display.getDefault().asyncExec(new Runnable() { public void run() { // don't use getShell(event) here since @@ -119,18 +118,17 @@ public class MergeCommand extends UIText.MergeAction_MergeCanceledMessage); } }); - } else if (!result.isOK()) { + else if (!result.isOK()) Activator.handleError(result.getMessage(), result .getException(), true); - } else { + else Display.getDefault().asyncExec(new Runnable() { public void run() { Shell shell = PlatformUI.getWorkbench() .getActiveWorkbenchWindow().getShell(); - new MergeResultDialog(shell, repository, op.getResult()).open(); + MergeResultDialog.getDialog(shell, repository, op.getResult()).open(); } }); - } } }); job.schedule(); @@ -159,9 +157,8 @@ public class MergeCommand extends ex = e; } - if (message != null) { + if (message != null) Activator.handleError(UIText.MergeAction_CannotMerge, ex, true); - } return (message == null); } } diff --git a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties index 6fbae53d1b..ea7d2d1e68 100644 --- a/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties +++ b/org.eclipse.egit.ui/src/org/eclipse/egit/ui/uitext.properties @@ -237,6 +237,7 @@ GitProjectPropertyPage_ValueUnbornBranch=None (unborn branch) GitProjectsImportPage_NoProjectsMessage=No projects found ClearCredentialsCommand_clearingCredentialsFailed=Clearing credentials failed. +CheckoutConflictDialog_conflictMessage=The files shown below have uncommitted changes which would be lost by the selected operation.\n\nEither commit the changes to the repository or discard the changes by resetting the current branch. CheckoutDialog_Message=Select a ref and choose action to execute CheckoutDialog_OkCheckout=&Checkout CheckoutDialog_Title=Checkout a ref or work with branches |
