diff --git a/platform/lang-impl/src/com/intellij/webcore/packaging/PackagesNotificationPanel.java b/platform/lang-impl/src/com/intellij/webcore/packaging/PackagesNotificationPanel.java index 0795c482f0f2..cb281cb3d7af 100644 --- a/platform/lang-impl/src/com/intellij/webcore/packaging/PackagesNotificationPanel.java +++ b/platform/lang-impl/src/com/intellij/webcore/packaging/PackagesNotificationPanel.java @@ -141,4 +141,8 @@ public class PackagesNotificationPanel { return dimension; } } + + public void removeLinkHandler(String key) { + myLinkHandlers.remove(key); + } } diff --git a/platform/platform-impl/src/com/intellij/remote/VagrantNotStartedException.java b/platform/platform-impl/src/com/intellij/remote/VagrantNotStartedException.java new file mode 100644 index 000000000000..e73341f14cd9 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/remote/VagrantNotStartedException.java @@ -0,0 +1,32 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.remote; + +/** + * @author traff + */ +public class VagrantNotStartedException extends RuntimeException { + private String myVagrantFolder; + + public VagrantNotStartedException(String message, String vagrantFolder) { + super(message); + myVagrantFolder = vagrantFolder; + } + + public String getVagrantFolder() { + return myVagrantFolder; + } +} diff --git a/platform/platform-impl/src/com/intellij/remote/VagrantSupport.java b/platform/platform-impl/src/com/intellij/remote/VagrantSupport.java index 07ca873f29dc..a5ebae6fe567 100644 --- a/platform/platform-impl/src/com/intellij/remote/VagrantSupport.java +++ b/platform/platform-impl/src/com/intellij/remote/VagrantSupport.java @@ -15,6 +15,7 @@ */ package com.intellij.remote; +import com.intellij.execution.ExecutionException; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; @@ -57,6 +58,8 @@ public abstract class VagrantSupport { public abstract boolean checkVagrantRunning(String folder, boolean runIfDown); + public abstract void runVagrant(String folder) throws ExecutionException; + public abstract Collection getVagrantInstancesConnectors(@NotNull Project project); public abstract boolean isVagrantInstance(VirtualFile dir); diff --git a/python/openapi/src/com/jetbrains/python/packaging/PyExternalProcessException.java b/python/openapi/src/com/jetbrains/python/packaging/PyExternalProcessException.java index 40d1f31861a9..06e233717fd6 100644 --- a/python/openapi/src/com/jetbrains/python/packaging/PyExternalProcessException.java +++ b/python/openapi/src/com/jetbrains/python/packaging/PyExternalProcessException.java @@ -16,6 +16,7 @@ package com.jetbrains.python.packaging; import com.intellij.execution.ExecutionException; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; @@ -34,6 +35,8 @@ public class PyExternalProcessException extends ExecutionException { @NotNull private List myArgs; @NotNull private String myMessage; + private Pair myHandler = null; + public PyExternalProcessException(int retcode, @NotNull String name, @NotNull List args, @NotNull String message) { super(String.format("External process error '%s %s':\n%s", name, StringUtil.join(args, " "), message)); myRetcode = retcode; @@ -92,4 +95,18 @@ public class PyExternalProcessException extends ExecutionException { } return StringUtil.join(result, ""); } + + public PyExternalProcessException withHandler(@NotNull String name, @NotNull Runnable handler) { + myHandler = Pair.create(name, handler); + return this; + } + + + public boolean hasHandler() { + return myHandler != null; + } + + public Pair getHandler() { + return myHandler; + } } diff --git a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java index 0b65e7000825..4a4f016b5579 100644 --- a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java +++ b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java @@ -52,6 +52,7 @@ import com.intellij.openapi.vfs.newvfs.events.VFileEvent; import com.intellij.remote.RemoteFile; import com.intellij.remote.RemoteSdkAdditionalData; import com.intellij.remote.RemoteSdkCredentials; +import com.intellij.remote.VagrantNotStartedException; import com.intellij.util.ArrayUtil; import com.intellij.util.Function; import com.intellij.util.PathMappingSettings; @@ -98,6 +99,9 @@ public class PyPackageManagerImpl extends PyPackageManager { public static final int ERROR_EXECUTION = -6; public static final int ERROR_INTERRUPTED = -7; + public static final int ERROR_VAGRANT_NOT_LAUNCHED = 101; + public static final int ERROR_REMOTE_ACCESS = 102; + public static final String PACKAGE_PIP = "pip"; public static final String PACKAGE_DISTRIBUTE = "distribute"; public static final String PACKAGE_SETUPTOOLS = "setuptools"; @@ -121,6 +125,7 @@ public class PyPackageManagerImpl extends PyPackageManager { public static final String SETUPTOOLS = PACKAGE_SETUPTOOLS + "-" + SETUPTOOLS_VERSION; public static final String PIP = PACKAGE_PIP + "-" + PIP_VERSION; + private static final String LAUNCH_VAGRANT = "launchVagrant"; private List myPackagesCache = null; private Map> myDependenciesCache = null; @@ -790,12 +795,37 @@ public class PyPackageManagerImpl extends PyPackageManager { if (sdkData instanceof PyRemoteSdkAdditionalDataBase) { //remote interpreter RemoteSdkCredentials remoteSdkCredentials; try { - remoteSdkCredentials = ((RemoteSdkAdditionalData)sdkData).getRemoteSdkCredentials(); + remoteSdkCredentials = ((RemoteSdkAdditionalData)sdkData).getRemoteSdkCredentials(false); } catch (InterruptedException e) { LOG.error(e); remoteSdkCredentials = null; } + catch (final ExecutionException e) { + if (e.getCause() instanceof VagrantNotStartedException) { + throw new PyExternalProcessException(ERROR_VAGRANT_NOT_LAUNCHED, helperPath, args, "Vagrant instance is down. Launch vagrant").withHandler(LAUNCH_VAGRANT, new Runnable() { + @Override + public void run() { + final PythonRemoteInterpreterManager manager = PythonRemoteInterpreterManager.getInstance(); + if (manager != null) { + + try { + manager.runVagrant(((VagrantNotStartedException)e.getCause()).getVagrantFolder()); + clearCaches(); + + } + catch (ExecutionException e1) { + throw new RuntimeException(e1); + } + } + } + }); + } else { + throw new PyExternalProcessException(ERROR_REMOTE_ACCESS, helperPath, args, e.getMessage()); + } + } final PythonRemoteInterpreterManager manager = PythonRemoteInterpreterManager.getInstance(); if (manager != null && remoteSdkCredentials != null) { final List cmdline = new ArrayList(); diff --git a/python/src/com/jetbrains/python/packaging/ui/PyInstalledPackagesPanel.java b/python/src/com/jetbrains/python/packaging/ui/PyInstalledPackagesPanel.java index 0fdbc53a5586..e0c0e3074e0c 100644 --- a/python/src/com/jetbrains/python/packaging/ui/PyInstalledPackagesPanel.java +++ b/python/src/com/jetbrains/python/packaging/ui/PyInstalledPackagesPanel.java @@ -125,7 +125,22 @@ public class PyInstalledPackagesPanel extends InstalledPackagesPanel { } final boolean hasPackagingTools = myHasPip && myHasSetuptools; allowCreateVirtualEnv &= !hasPackagingTools; + + if (externalProcessException.hasHandler()) { + final String key = externalProcessException.getHandler().first; + myNotificationArea.addLinkHandler(key, + new Runnable() { + @Override + public void run() { + externalProcessException.getHandler().second.run(); + myNotificationArea.removeLinkHandler(key); + updateNotifications(selectedSdk); + } + } + ); + } } + if (text == null) { if (!myHasSetuptools) { text = "Python package management tools not found. Install 'setuptools'"; @@ -186,7 +201,7 @@ public class PyInstalledPackagesPanel extends InstalledPackagesPanel { protected boolean canUninstallPackage(InstalledPackage pkg) { if (!myHasPip) return false; if (PythonSdkType.isVirtualEnv(getSelectedSdk()) && pkg instanceof PyPackage) { - final String location = ((PyPackage) pkg).getLocation(); + final String location = ((PyPackage)pkg).getLocation(); if (location != null && location.startsWith(PyPackageManagerImpl.getUserSite())) { return false; } diff --git a/python/src/com/jetbrains/python/remote/PythonRemoteInterpreterManager.java b/python/src/com/jetbrains/python/remote/PythonRemoteInterpreterManager.java index c2fba7a002d8..b904b554570b 100644 --- a/python/src/com/jetbrains/python/remote/PythonRemoteInterpreterManager.java +++ b/python/src/com/jetbrains/python/remote/PythonRemoteInterpreterManager.java @@ -170,7 +170,9 @@ public abstract class PythonRemoteInterpreterManager { @Nullable public abstract RemoteCredentials getVagrantRemoteCredentials(VagrantBasedCredentialsHolder data) throws IOException; - public abstract boolean checkVagrantStatus(VagrantBasedCredentialsHolder data, boolean runIfDown); + public abstract boolean checkVagrantStatus(String vagrantFolder, boolean runIfDown); + + public abstract void runVagrant(String vagrantFolder) throws ExecutionException; public abstract void checkVagrantStatus(VagrantBasedCredentialsHolder data);