diff options
Diffstat (limited to 'python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java')
-rw-r--r-- | python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java | 665 |
1 files changed, 103 insertions, 562 deletions
diff --git a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java index 65d95eb62713..9b5f669168f7 100644 --- a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java +++ b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java @@ -15,31 +15,17 @@ */ package com.jetbrains.python.packaging; -import com.google.common.collect.Collections2; import com.google.common.collect.Lists; import com.intellij.execution.ExecutionException; import com.intellij.execution.process.ProcessOutput; import com.intellij.execution.util.ExecUtil; -import com.intellij.icons.AllIcons; -import com.intellij.notification.Notification; -import com.intellij.notification.NotificationListener; -import com.intellij.notification.NotificationType; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.progress.ProgressManager; -import com.intellij.openapi.progress.Task; -import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.openapi.projectRoots.SdkAdditionalData; import com.intellij.openapi.projectRoots.impl.ProjectJdkImpl; import com.intellij.openapi.roots.OrderRootType; -import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.Key; -import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; @@ -49,46 +35,36 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.newvfs.BulkFileListener; 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; -import com.intellij.util.SystemProperties; import com.intellij.util.containers.HashSet; import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.net.HttpConfigurable; -import com.intellij.webcore.packaging.PackagesNotificationPanel; import com.jetbrains.python.PythonHelpersLocator; import com.jetbrains.python.psi.LanguageLevel; import com.jetbrains.python.psi.PyExpression; import com.jetbrains.python.psi.PyListLiteralExpression; import com.jetbrains.python.psi.PyStringLiteralExpression; -import com.jetbrains.python.remote.PyRemoteSdkAdditionalDataBase; -import com.jetbrains.python.remote.PythonRemoteInterpreterManager; import com.jetbrains.python.sdk.PySdkUtil; import com.jetbrains.python.sdk.PythonSdkType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import javax.swing.event.HyperlinkEvent; -import java.awt.*; import java.io.File; import java.io.IOException; import java.util.*; -import java.util.List; /** * @author vlan */ -@SuppressWarnings({"UnusedDeclaration", "FieldAccessedSynchronizedAndUnsynchronized"}) public class PyPackageManagerImpl extends PyPackageManager { - private static final Logger LOG = Logger.getInstance(PyPackageManagerImpl.class); + // Bundled versions of package management tools + public static final String SETUPTOOLS_VERSION = "1.1.5"; + public static final String PIP_VERSION = "1.4.1"; + + public static final String SETUPTOOLS = PACKAGE_SETUPTOOLS + "-" + SETUPTOOLS_VERSION; + public static final String PIP = PACKAGE_PIP + "-" + PIP_VERSION; public static final int OK = 0; - public static final int ERROR_WRONG_USAGE = 1; public static final int ERROR_NO_PIP = 2; public static final int ERROR_NO_SETUPTOOLS = 3; public static final int ERROR_INVALID_SDK = -1; @@ -97,260 +73,24 @@ public class PyPackageManagerImpl extends PyPackageManager { public static final int ERROR_INVALID_OUTPUT = -4; public static final int ERROR_ACCESS_DENIED = -5; 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"; - - public static final Key<Boolean> RUNNING_PACKAGING_TASKS = Key.create("PyPackageRequirementsInspection.RunningPackagingTasks"); + private static final Logger LOG = Logger.getInstance(PyPackageManagerImpl.class); private static final String PACKAGING_TOOL = "packaging_tool.py"; private static final String VIRTUALENV = "virtualenv.py"; private static final int TIMEOUT = 10 * 60 * 1000; private static final String BUILD_DIR_OPTION = "--build-dir"; - public static final String USE_USER_SITE = "--user"; public static final String INSTALL = "install"; public static final String UNINSTALL = "uninstall"; public static final String UNTAR = "untar"; - // Bundled versions of package management tools - public static final String SETUPTOOLS_VERSION = "1.1.5"; - public static final String PIP_VERSION = "1.4.1"; - - 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<PyPackage> myPackagesCache = null; private Map<String, Set<PyPackage>> myDependenciesCache = null; private PyExternalProcessException myExceptionCache = null; - private Sdk mySdk; - - public static class UI { - @Nullable private Listener myListener; - @NotNull private Project myProject; - @NotNull private Sdk mySdk; - - public interface Listener { - void started(); - - void finished(List<PyExternalProcessException> exceptions); - } - - public UI(@NotNull Project project, @NotNull Sdk sdk, @Nullable Listener listener) { - myProject = project; - mySdk = sdk; - myListener = listener; - } - - public void installManagement(@NotNull final String name) { - final String progressTitle; - final String successTitle; - progressTitle = "Installing package " + name; - successTitle = "Packages installed successfully"; - run(new MultiExternalRunnable() { - @Override - public List<PyExternalProcessException> run(@NotNull ProgressIndicator indicator) { - final List<PyExternalProcessException> exceptions = new ArrayList<PyExternalProcessException>(); - indicator.setText(String.format("Installing package '%s'...", name)); - final PyPackageManagerImpl manager = (PyPackageManagerImpl)PyPackageManagers.getInstance().forSdk(mySdk); - try { - manager.installManagement(name); - } - catch (PyExternalProcessException e) { - exceptions.add(e); - } - return exceptions; - } - }, progressTitle, successTitle, "Installed package " + name, - "Install package failed" - ); - } - - public void install(@NotNull final List<PyRequirement> requirements, @NotNull final List<String> extraArgs) { - final String progressTitle; - final String successTitle; - progressTitle = "Installing packages"; - successTitle = "Packages installed successfully"; - run(new MultiExternalRunnable() { - @Override - public List<PyExternalProcessException> run(@NotNull ProgressIndicator indicator) { - final int size = requirements.size(); - final List<PyExternalProcessException> exceptions = new ArrayList<PyExternalProcessException>(); - final PyPackageManagerImpl manager = (PyPackageManagerImpl)PyPackageManagers.getInstance().forSdk(mySdk); - for (int i = 0; i < size; i++) { - final PyRequirement requirement = requirements.get(i); - if (myListener != null) { - indicator.setText(String.format("Installing package '%s'...", requirement)); - indicator.setFraction((double)i / size); - } - try { - manager.install(list(requirement), extraArgs); - } - catch (PyExternalProcessException e) { - exceptions.add(e); - } - } - manager.refresh(); - return exceptions; - } - }, progressTitle, successTitle, "Installed packages: " + PyPackageUtil.requirementsToString(requirements), - "Install packages failed" - ); - } - - public void uninstall(@NotNull final List<PyPackage> packages) { - final String packagesString = StringUtil.join(packages, new Function<PyPackage, String>() { - @Override - public String fun(PyPackage pkg) { - return "'" + pkg.getName() + "'"; - } - }, ", "); - if (checkDependents(packages)) return; - - run(new MultiExternalRunnable() { - @Override - public List<PyExternalProcessException> run(@NotNull ProgressIndicator indicator) { - final PyPackageManagerImpl manager = (PyPackageManagerImpl)PyPackageManagers.getInstance().forSdk(mySdk); - try { - manager.uninstall(packages); - return list(); - } - catch (PyExternalProcessException e) { - return list(e); - } - finally { - manager.refresh(); - } - } - }, "Uninstalling packages", "Packages uninstalled successfully", "Uninstalled packages: " + packagesString, - "Uninstall packages failed" - ); - } - - private boolean checkDependents(@NotNull final List<PyPackage> packages) { - try { - final Map<String, Set<PyPackage>> dependentPackages = collectDependents(packages, mySdk); - final int[] warning = {0}; - if (!dependentPackages.isEmpty()) { - ApplicationManager.getApplication().invokeAndWait(new Runnable() { - @Override - public void run() { - if (dependentPackages.size() == 1) { - String message = "You are attempting to uninstall "; - List<String> dep = new ArrayList<String>(); - int size = 1; - for (Map.Entry<String, Set<PyPackage>> entry : dependentPackages.entrySet()) { - final Set<PyPackage> value = entry.getValue(); - size = value.size(); - dep.add(entry.getKey() + " package which is required for " + StringUtil.join(value, ", ")); - } - message += StringUtil.join(dep, "\n"); - message += size == 1 ? " package" : " packages"; - message += "\n\nDo you want to proceed?"; - warning[0] = Messages.showYesNoDialog(message, "Warning", - AllIcons.General.BalloonWarning); - } - else { - String message = "You are attempting to uninstall packages which are required for another packages.\n\n"; - List<String> dep = new ArrayList<String>(); - for (Map.Entry<String, Set<PyPackage>> entry : dependentPackages.entrySet()) { - dep.add(entry.getKey() + " -> " + StringUtil.join(entry.getValue(), ", ")); - } - message += StringUtil.join(dep, "\n"); - message += "\n\nDo you want to proceed?"; - warning[0] = Messages.showYesNoDialog(message, "Warning", - AllIcons.General.BalloonWarning); - } - } - }, ModalityState.current()); - } - if (warning[0] != Messages.YES) return true; - } - catch (PyExternalProcessException e) { - LOG.info("Error loading packages dependents: " + e.getMessage(), e); - } - return false; - } - - private interface MultiExternalRunnable { - List<PyExternalProcessException> run(@NotNull ProgressIndicator indicator); - } - - private void run(@NotNull final MultiExternalRunnable runnable, @NotNull final String progressTitle, - @NotNull final String successTitle, @NotNull final String successDescription, @NotNull final String failureTitle) { - ProgressManager.getInstance().run(new Task.Backgroundable(myProject, progressTitle, false) { - @Override - public void run(@NotNull ProgressIndicator indicator) { - indicator.setText(progressTitle + "..."); - final Ref<Notification> notificationRef = new Ref<Notification>(null); - final String PACKAGING_GROUP_ID = "Packaging"; - final Application application = ApplicationManager.getApplication(); - if (myListener != null) { - application.invokeLater(new Runnable() { - @Override - public void run() { - myListener.started(); - } - }); - } - - final List<PyExternalProcessException> exceptions = runnable.run(indicator); - if (exceptions.isEmpty()) { - notificationRef.set(new Notification(PACKAGING_GROUP_ID, successTitle, successDescription, NotificationType.INFORMATION)); - } - else { - final String progressLower = progressTitle.toLowerCase(); - final String firstLine = String.format("Error%s occurred when %s.", exceptions.size() > 1 ? "s" : "", progressLower); - - final String description = createDescription(exceptions, firstLine); - notificationRef.set(new Notification(PACKAGING_GROUP_ID, failureTitle, - firstLine + " <a href=\"xxx\">Details...</a>", - NotificationType.ERROR, - new NotificationListener() { - @Override - public void hyperlinkUpdate(@NotNull Notification notification, - @NotNull HyperlinkEvent event) { - assert myProject != null; - PackagesNotificationPanel.showError(myProject, failureTitle, description); - } - } - )); - } - application.invokeLater(new Runnable() { - @Override - public void run() { - if (myListener != null) { - myListener.finished(exceptions); - } - final Notification notification = notificationRef.get(); - if (notification != null) { - notification.notify(myProject); - } - } - }); - } - }); - } - - public static String createDescription(List<PyExternalProcessException> exceptions, String firstLine) { - final StringBuilder b = new StringBuilder(); - b.append(firstLine); - b.append("\n\n"); - for (PyExternalProcessException exception : exceptions) { - b.append(exception.toString()); - b.append("\n"); - } - return b.toString(); - } - } + protected Sdk mySdk; @Override public void refresh() { @@ -373,7 +113,23 @@ public class PyPackageManagerImpl extends PyPackageManager { }); } - private void installManagement(String name) throws PyExternalProcessException { + @Override + public void installManagement() throws PyExternalProcessException { + if (!hasPackage(PACKAGE_SETUPTOOLS, false) && !hasPackage(PACKAGE_DISTRIBUTE, false)) { + installManagement(SETUPTOOLS); + } + if (!hasPackage(PACKAGE_PIP, false)) { + installManagement(PIP); + } + } + + @Override + public boolean hasManagement(boolean cachedOnly) { + return (hasPackage(PACKAGE_SETUPTOOLS, cachedOnly) || hasPackage(PACKAGE_DISTRIBUTE, cachedOnly)) && + hasPackage(PACKAGE_PIP, cachedOnly); + } + + protected void installManagement(@NotNull String name) throws PyExternalProcessException { final String helperPath = getHelperPath(name); ArrayList<String> args = Lists.newArrayList(UNTAR, helperPath); @@ -390,7 +146,7 @@ public class PyPackageManagerImpl extends PyPackageManager { } final String fileName = dirName + name + File.separatorChar + "setup.py"; try { - output = getProcessOutput(fileName, Collections.<String>singletonList(INSTALL), true, dirName + name); + output = getProcessOutput(fileName, Collections.singletonList(INSTALL), true, dirName + name); final int retcode = output.getExitCode(); if (output.isTimeout()) { throw new PyExternalProcessException(ERROR_TIMEOUT, fileName, Lists.newArrayList(INSTALL), "Timed out"); @@ -406,17 +162,28 @@ public class PyPackageManagerImpl extends PyPackageManager { } finally { clearCaches(); - FileUtil.delete(new File(dirName)); //TODO: remove temp directory for remote interpreter + FileUtil.delete(new File(dirName)); + } + } + + private boolean hasPackage(@NotNull String name, boolean cachedOnly) { + try { + return findPackage(name, cachedOnly) != null; + } + catch (PyExternalProcessException ignored) { + return false; } } PyPackageManagerImpl(@NotNull Sdk sdk) { mySdk = sdk; + subscribeToLocalChanges(sdk); + } + + protected void subscribeToLocalChanges(Sdk sdk) { final Application app = ApplicationManager.getApplication(); final MessageBusConnection connection = app.getMessageBus().connect(); - if (!PySdkUtil.isRemote(sdk)) { - connection.subscribe(VirtualFileManager.VFS_CHANGES, new MySdkRootWatcher()); - } + connection.subscribe(VirtualFileManager.VFS_CHANGES, new MySdkRootWatcher()); } public Sdk getSdk() { @@ -424,27 +191,13 @@ public class PyPackageManagerImpl extends PyPackageManager { } @Override - public void install(String requirementString) throws PyExternalProcessException { - boolean hasSetuptools = false; - boolean hasPip = false; - try { - hasSetuptools = findInstalledPackage(SETUPTOOLS) != null; - } - catch (PyExternalProcessException ignored) { - } - try { - hasPip = findInstalledPackage(PIP) != null; - } - catch (PyExternalProcessException ignored) { - } - - if (!hasSetuptools) installManagement(SETUPTOOLS); - if (!hasPip) installManagement(PIP); + public void install(@NotNull String requirementString) throws PyExternalProcessException { + installManagement(); install(Collections.singletonList(PyRequirement.fromString(requirementString)), Collections.<String>emptyList()); } - public void install(@NotNull List<PyRequirement> requirements, @NotNull List<String> extraArgs) - throws PyExternalProcessException { + @Override + public void install(@NotNull List<PyRequirement> requirements, @NotNull List<String> extraArgs) throws PyExternalProcessException { final List<String> args = new ArrayList<String>(); args.add(INSTALL); final File buildDir; @@ -455,7 +208,7 @@ public class PyPackageManagerImpl extends PyPackageManager { throw new PyExternalProcessException(ERROR_ACCESS_DENIED, PACKAGING_TOOL, args, "Cannot create temporary build directory"); } if (!extraArgs.contains(BUILD_DIR_OPTION)) { - args.addAll(list(BUILD_DIR_OPTION, buildDir.getAbsolutePath())); + args.addAll(Arrays.asList(BUILD_DIR_OPTION, buildDir.getAbsolutePath())); } boolean useUserSite = extraArgs.contains(USE_USER_SITE); @@ -499,69 +252,22 @@ public class PyPackageManagerImpl extends PyPackageManager { } } - private static Map<String, Set<PyPackage>> collectDependents(@NotNull final List<PyPackage> packages, Sdk sdk) - throws PyExternalProcessException { - Map<String, Set<PyPackage>> dependentPackages = new HashMap<String, Set<PyPackage>>(); - for (PyPackage pkg : packages) { - final Set<PyPackage> dependents = - ((PyPackageManagerImpl)PyPackageManager.getInstance(sdk)).getDependents(pkg.getName()); - if (dependents != null && !dependents.isEmpty()) { - for (PyPackage dependent : dependents) { - if (!packages.contains(dependent)) { - dependentPackages.put(pkg.getName(), dependents); - } - } - } - } - return dependentPackages; - } - - public static String getUserSite() { - if (SystemInfo.isWindows) { - final String appdata = System.getenv("APPDATA"); - return appdata + File.separator + "Python"; - } - else { - final String userHome = SystemProperties.getUserHome(); - return userHome + File.separator + ".local"; - } - } - - - public boolean cacheIsNotNull() { - return myPackagesCache != null; - } - - /** - * Returns the list of packages for the SDK without initiating a remote connection. Returns null - * for a remote interpreter if the list of packages was not loaded. - * - * @return the list of packages or null - */ @Nullable - public synchronized List<PyPackage> getPackagesFast() throws PyExternalProcessException { - if (myPackagesCache != null) { - return myPackagesCache; - } - if (PySdkUtil.isRemote(mySdk)) { - return null; - } - return getPackages(); - } - - @NotNull - public synchronized List<PyPackage> getPackages() throws PyExternalProcessException { + public synchronized List<PyPackage> getPackages(boolean cachedOnly) throws PyExternalProcessException { if (myPackagesCache == null) { if (myExceptionCache != null) { throw myExceptionCache; } - + if (cachedOnly) { + return null; + } loadPackages(); } return myPackagesCache; } - public synchronized Set<PyPackage> getDependents(String pkg) throws PyExternalProcessException { + @Nullable + public synchronized Set<PyPackage> getDependents(@NotNull PyPackage pkg) throws PyExternalProcessException { if (myDependenciesCache == null) { if (myExceptionCache != null) { throw myExceptionCache; @@ -569,12 +275,12 @@ public class PyPackageManagerImpl extends PyPackageManager { loadPackages(); } - return myDependenciesCache.get(pkg); + return myDependenciesCache.get(pkg.getName()); } public synchronized void loadPackages() throws PyExternalProcessException { try { - final String output = runPythonHelper(PACKAGING_TOOL, list("list")); + final String output = runPythonHelper(PACKAGING_TOOL, Arrays.asList("list")); myPackagesCache = parsePackagingToolOutput(output); Collections.sort(myPackagesCache, new Comparator<PyPackage>() { @Override @@ -592,7 +298,7 @@ public class PyPackageManagerImpl extends PyPackageManager { } } - private void calculateDependents() { + private synchronized void calculateDependents() { myDependenciesCache = new HashMap<String, Set<PyPackage>>(); for (PyPackage p : myPackagesCache) { final List<PyRequirement> requirements = p.getRequirements(); @@ -608,47 +314,18 @@ public class PyPackageManagerImpl extends PyPackageManager { @Override @Nullable - public PyPackage findInstalledPackage(String name) throws PyExternalProcessException { - return findPackageByName(name, getPackages()); - } - - @Override - public boolean findPackage(@NotNull final String name) { - try { - final String output = runPythonHelper(PACKAGING_TOOL, list("search", name)); - return StringUtil.containsIgnoreCase(output, name + " "); - } - catch (PyExternalProcessException e) { - LOG.error(e.getMessage()); - return false; - } - } - - @Nullable - public PyPackage findPackageFast(String name) throws PyExternalProcessException { - final List<PyPackage> packages = getPackagesFast(); - return packages != null ? findPackageByName(name, packages) : null; - } - - @Nullable - private static PyPackage findPackageByName(String name, List<PyPackage> packages) { - for (PyPackage pkg : packages) { - if (name.equalsIgnoreCase(pkg.getName())) { - return pkg; + public PyPackage findPackage(@NotNull String name, boolean cachedOnly) throws PyExternalProcessException { + final List<PyPackage> packages = getPackages(cachedOnly); + if (packages != null) { + for (PyPackage pkg : packages) { + if (name.equalsIgnoreCase(pkg.getName())) { + return pkg; + } } } return null; } - public boolean hasPip() { - try { - return findPackageFast(PACKAGE_PIP) != null; - } - catch (PyExternalProcessException e) { - return false; - } - } - @NotNull public String createVirtualEnv(@NotNull String destinationDir, boolean useGlobalSite) throws PyExternalProcessException { final List<String> args = new ArrayList<String>(); @@ -674,30 +351,21 @@ public class PyPackageManagerImpl extends PyPackageManager { final String path = (binary != null) ? binary : binaryFallback; if (usePyVenv) { - // TODO: Still no 'packaging' and 'pysetup3' for Python 3.3rc1, see PEP 405 + // Still no 'packaging' and 'pysetup3' for Python 3.3rc1, see PEP 405 final VirtualFile binaryFile = LocalFileSystem.getInstance().refreshAndFindFileByPath(path); if (binaryFile != null) { final ProjectJdkImpl tmpSdk = new ProjectJdkImpl("", PythonSdkType.getInstance()); tmpSdk.setHomePath(path); - final PyPackageManagerImpl manager = new PyPackageManagerImpl(tmpSdk); - manager.installManagement(SETUPTOOLS); - manager.installManagement(PIP); + final PyPackageManager manager = PyPackageManager.getInstance(tmpSdk); + manager.installManagement(); } } return path; } - public static void deleteVirtualEnv(@NotNull String sdkHome) throws PyExternalProcessException { - final File root = PythonSdkType.getVirtualEnvRoot(sdkHome); - if (root != null) { - FileUtil.delete(root); - } - } - @Nullable - public static List<PyRequirement> getRequirements(@NotNull Module module) { - // TODO: Cache requirements, clear cache on requirements.txt or setup.py updates - List<PyRequirement> requirements = getRequirementsFromTxt(module); + public List<PyRequirement> getRequirements(@NotNull Module module) { + List<PyRequirement> requirements = PySdkUtil.getRequirementsFromTxt(module); if (requirements != null) { return requirements; } @@ -721,25 +389,12 @@ public class PyPackageManagerImpl extends PyPackageManager { return null; } - @Nullable - public static List<PyRequirement> getRequirementsFromTxt(Module module) { - final VirtualFile requirementsTxt = PyPackageUtil.findRequirementsTxt(module); - if (requirementsTxt != null) { - return PyRequirement.parse(requirementsTxt); - } - return null; - } - - private void clearCaches() { + protected synchronized void clearCaches() { myPackagesCache = null; myDependenciesCache = null; myExceptionCache = null; } - private static <T> List<T> list(T... xs) { - return Arrays.asList(xs); - } - @Nullable private static String getProxyString() { final HttpConfigurable settings = HttpConfigurable.getInstance(); @@ -792,164 +447,61 @@ public class PyPackageManagerImpl extends PyPackageManager { } @Nullable - private String getHelperPath(String helper) { - String helperPath; - final SdkAdditionalData sdkData = mySdk.getSdkAdditionalData(); - if (sdkData instanceof PyRemoteSdkAdditionalDataBase) { - PyRemoteSdkAdditionalDataBase remoteSdkData = (PyRemoteSdkAdditionalDataBase)mySdk.getSdkAdditionalData(); - - try { - final RemoteSdkCredentials remoteSdkCredentials = remoteSdkData.getRemoteSdkCredentials(false); - if (!StringUtil.isEmpty(remoteSdkCredentials.getHelpersPath())) { - helperPath = new RemoteFile(remoteSdkCredentials.getHelpersPath(), - helper).getPath(); - } - else { - helperPath = null; - } - } - catch (Exception e) { - helperPath = null; - LOG.error(e); - } - } - else { - helperPath = PythonHelpersLocator.getHelperPath(helper); - } - return helperPath; + protected String getHelperPath(String helper) { + return PythonHelpersLocator.getHelperPath(helper); } - private ProcessOutput getProcessOutput(@NotNull String helperPath, + protected ProcessOutput getProcessOutput(@NotNull String helperPath, @NotNull List<String> args, boolean askForSudo, - @Nullable String workingDir) - throws PyExternalProcessException { - final SdkAdditionalData sdkData = mySdk.getSdkAdditionalData(); + @Nullable String workingDir) throws PyExternalProcessException { final String homePath = mySdk.getHomePath(); if (homePath == null) { throw new PyExternalProcessException(ERROR_INVALID_SDK, helperPath, args, "Cannot find interpreter for SDK"); } - if (sdkData instanceof PyRemoteSdkAdditionalDataBase) { //remote interpreter - RemoteSdkCredentials remoteSdkCredentials; + if (workingDir == null) { + workingDir = new File(homePath).getParent(); + } + final List<String> cmdline = new ArrayList<String>(); + cmdline.add(homePath); + cmdline.add(helperPath); + cmdline.addAll(args); + LOG.info("Running packaging tool: " + StringUtil.join(cmdline, " ")); + + final boolean canCreate = FileUtil.ensureCanCreateFile(new File(homePath)); + if (!canCreate && !SystemInfo.isWindows && askForSudo) { //is system site interpreter --> we need sudo privileges try { - 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. <a href=\"" + - LAUNCH_VAGRANT + - "\">Launch vagrant</a>") - .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<String> cmdline = new ArrayList<String>(); - cmdline.add(homePath); - cmdline.add(RemoteFile.detectSystemByPath(homePath).createRemoteFile(helperPath).getPath()); - cmdline.addAll(Collections2.transform(args, new com.google.common.base.Function<String, String>() { - @Override - public String apply(@Nullable String input) { - return quoteIfNeeded(input); + final ProcessOutput result = ExecUtil.sudoAndGetOutput(cmdline, + "Please enter your password to make changes in system packages: ", + workingDir); + String message = result.getStderr(); + if (result.getExitCode() != 0) { + final String stdout = result.getStdout(); + if (StringUtil.isEmptyOrSpaces(message)) { + message = stdout; } - })); - try { - if (askForSudo) { - askForSudo = !manager.ensureCanWrite(null, remoteSdkCredentials, remoteSdkCredentials.getInterpreterPath()); + if (StringUtil.isEmptyOrSpaces(message)) { + message = "Failed to perform action. Permission denied."; } - ProcessOutput processOutput; - do { - PathMappingSettings mappings = manager.setupMappings(null, (PyRemoteSdkAdditionalDataBase)sdkData, null); - processOutput = - manager.runRemoteProcess(null, remoteSdkCredentials, mappings, ArrayUtil.toStringArray(cmdline), workingDir, askForSudo); - if (askForSudo && processOutput.getStderr().contains("sudo: 3 incorrect password attempts")) { - continue; - } - break; - } - while (true); - return processOutput; + throw new PyExternalProcessException(result.getExitCode(), helperPath, args, message); } - catch (ExecutionException e) { - throw new PyExternalProcessException(ERROR_INVALID_SDK, helperPath, args, "Error running SDK: " + e.getMessage(), e); + if (SystemInfo.isMac && !StringUtil.isEmptyOrSpaces(message)) { + throw new PyExternalProcessException(result.getExitCode(), helperPath, args, message); } + return result; } - else { - throw new PyExternalProcessException(ERROR_INVALID_SDK, helperPath, args, - PythonRemoteInterpreterManager.WEB_DEPLOYMENT_PLUGIN_IS_DISABLED); + catch (ExecutionException e) { + throw new PyExternalProcessException(ERROR_EXECUTION, helperPath, args, e.getMessage()); + } + catch (IOException e) { + throw new PyExternalProcessException(ERROR_ACCESS_DENIED, helperPath, args, e.getMessage()); } } else { - if (workingDir == null) { - workingDir = new File(homePath).getParent(); - } - final List<String> cmdline = new ArrayList<String>(); - cmdline.add(homePath); - cmdline.add(helperPath); - cmdline.addAll(args); - LOG.info("Running packaging tool: " + StringUtil.join(cmdline, " ")); - - final boolean canCreate = FileUtil.ensureCanCreateFile(new File(homePath)); - if (!canCreate && !SystemInfo.isWindows && askForSudo) { //is system site interpreter --> we need sudo privileges - try { - final ProcessOutput result = ExecUtil.sudoAndGetOutput(cmdline, - "Please enter your password to make changes in system packages: ", - workingDir); - String message = result.getStderr(); - if (result.getExitCode() != 0) { - final String stdout = result.getStdout(); - if (StringUtil.isEmptyOrSpaces(message)) { - message = stdout; - } - if (StringUtil.isEmptyOrSpaces(message)) { - message = "Failed to perform action. Permission denied."; - } - throw new PyExternalProcessException(result.getExitCode(), helperPath, args, message); - } - if (SystemInfo.isMac && !StringUtil.isEmptyOrSpaces(message)) { - throw new PyExternalProcessException(result.getExitCode(), helperPath, args, message); - } - return result; - } - catch (ExecutionException e) { - throw new PyExternalProcessException(ERROR_EXECUTION, helperPath, args, e.getMessage()); - } - catch (IOException e) { - throw new PyExternalProcessException(ERROR_ACCESS_DENIED, helperPath, args, e.getMessage()); - } - } - else { - return PySdkUtil.getProcessOutput(workingDir, ArrayUtil.toStringArray(cmdline), TIMEOUT); - } + return PySdkUtil.getProcessOutput(workingDir, ArrayUtil.toStringArray(cmdline), TIMEOUT); } } - private static String quoteIfNeeded(String arg) { - return arg.replace("<", "\\<").replace(">", "\\>"); //TODO: move this logic to ParametersListUtil.encode - } - @NotNull private static List<PyPackage> parsePackagingToolOutput(@NotNull String s) throws PyExternalProcessException { final String[] lines = StringUtil.splitByLines(s); @@ -976,17 +528,6 @@ public class PyPackageManagerImpl extends PyPackageManager { return packages; } - - @Override - public void showInstallationError(Project project, String title, String description) { - PackagesNotificationPanel.showError(project, title, description); - } - - @Override - public void showInstallationError(Component owner, String title, String description) { - PackagesNotificationPanel.showError(owner, title, description); - } - private class MySdkRootWatcher extends BulkFileListener.Adapter { @Override public void after(@NotNull List<? extends VFileEvent> events) { |