From 6065082ce0e47c2b46d75ac2e39899b0c80caffb Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Wed, 22 Aug 2012 20:35:49 +0400 Subject: [PATCH] Fixed refreshing SDK roots and updating current files after installing/uninstalling packages (PY-7250) --- .../python/packaging/PyPackageManager.java | 1 + .../packaging/PyPackageManagerImpl.java | 54 +++++++++++++------ .../python/packaging/ui/PyPackagesPanel.java | 2 +- 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/python/openapi/src/com/jetbrains/python/packaging/PyPackageManager.java b/python/openapi/src/com/jetbrains/python/packaging/PyPackageManager.java index 75f3da0232ad..f9afb731e0b9 100644 --- a/python/openapi/src/com/jetbrains/python/packaging/PyPackageManager.java +++ b/python/openapi/src/com/jetbrains/python/packaging/PyPackageManager.java @@ -14,4 +14,5 @@ public abstract class PyPackageManager { public abstract boolean hasPip(); public abstract void install(String requirementString) throws PyExternalProcessException; public abstract void showInstallationError(Project project, String title, String description); + public abstract void refresh(); } diff --git a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java index 165eee2f38f6..88acf9fd3490 100644 --- a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java +++ b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java @@ -22,22 +22,22 @@ 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; +import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VfsUtilCore; 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.NewVirtualFile; import com.intellij.openapi.vfs.newvfs.events.VFileEvent; import com.intellij.util.ArrayUtil; import com.intellij.util.Function; import com.intellij.util.SystemProperties; import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.net.HttpConfigurable; -import com.jetbrains.python.PyNames; import com.jetbrains.python.PythonHelpersLocator; import com.jetbrains.python.psi.PyExpression; import com.jetbrains.python.psi.PyListLiteralExpression; import com.jetbrains.python.psi.PyStringLiteralExpression; -import com.jetbrains.python.psi.search.PyProjectScopeBuilder; import com.jetbrains.python.remote.PyRemoteInterpreterException; import com.jetbrains.python.remote.PythonRemoteInterpreterManager; import com.jetbrains.python.remote.PythonRemoteSdkAdditionalData; @@ -154,6 +154,7 @@ public class PyPackageManagerImpl extends PyPackageManager { exceptions.add(e); } } + manager.refresh(); return exceptions; } }, progressTitle, successTitle, "Installed packages: " + PyPackageUtil.requirementsToString(requirements), @@ -171,13 +172,17 @@ public class PyPackageManagerImpl extends PyPackageManager { run(new MultiExternalRunnable() { @Override public List run(@NotNull ProgressIndicator indicator) { + final PyPackageManagerImpl manager = (PyPackageManagerImpl)PyPackageManagers.getInstance().forSdk(mySdk); try { - ((PyPackageManagerImpl)PyPackageManagers.getInstance().forSdk(mySdk)).uninstall(packages); + 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"); @@ -231,10 +236,6 @@ public class PyPackageManagerImpl extends PyPackageManager { if (myListener != null) { myListener.finished(exceptions); } - VirtualFileManager.getInstance().refreshWithoutFileWatcher(false); - if (exceptions.isEmpty()) { - PythonSdkType.getInstance().setupSdkPaths(mySdk); - } final Notification notification = notificationRef.get(); if (notification != null) { notification.notify(myProject); @@ -257,6 +258,36 @@ public class PyPackageManagerImpl extends PyPackageManager { } } + @Override + public void refresh() { + final Application application = ApplicationManager.getApplication(); + application.invokeLater(new Runnable() { + @Override + public void run() { + application.runWriteAction(new Runnable() { + @Override + public void run() { + syncFiles(mySdk.getRootProvider().getFiles(OrderRootType.CLASSES)); + } + }); + PythonSdkType.getInstance().setupSdkPaths(mySdk); + clearCaches(); + } + }); + } + + private void syncFiles(VirtualFile[] files) { + // Similar to LocalFileSystemImpl.syncFiles(), VirtualFile.refresh() doesn't run update index tasks immediately, so we get stale virtual + // files when we want to bind a stub to an AST. Another option is to use VirtualFileManager.refreshWithoutFileWatcher(), but it takes + // more time to refresh the whole local file system + for (VirtualFile root : files) { + if (root instanceof NewVirtualFile && root.getFileSystem() instanceof LocalFileSystem) { + ((NewVirtualFile)root).markDirtyRecursively(); + } + } + LocalFileSystem.getInstance().refreshFiles(Arrays.asList(files), false, true, null); + } + private void installManagement(String name) throws PyExternalProcessException { final File helperFile = PythonHelpersLocator.getHelperFile(name + ".tar.gz"); @@ -496,16 +527,9 @@ public class PyPackageManagerImpl extends PyPackageManager { return null; } - public void clearCaches() { + private void clearCaches() { myPackagesCache = null; myExceptionCache = null; - VirtualFile libDir = PyProjectScopeBuilder.findLibDir(mySdk); - if (libDir != null) { - VirtualFile sitePackages = libDir.findChild(PyNames.SITE_PACKAGES); - if (sitePackages != null) { - sitePackages.refresh(true, true); - } - } } private static List list(T... xs) { diff --git a/python/src/com/jetbrains/python/packaging/ui/PyPackagesPanel.java b/python/src/com/jetbrains/python/packaging/ui/PyPackagesPanel.java index 2d9cfd281776..070403435431 100644 --- a/python/src/com/jetbrains/python/packaging/ui/PyPackagesPanel.java +++ b/python/src/com/jetbrains/python/packaging/ui/PyPackagesPanel.java @@ -501,7 +501,7 @@ public class PyPackagesPanel extends JPanel { final String description = PyPackageManagerImpl.UI.createDescription(exceptions, firstLine); packageManager.showInstallationError(myProject, "Failed to install " + name, description); } - packageManager.clearCaches(); + packageManager.refresh(); updatePackages(sdk); for (Consumer listener : myPathChangedListeners) { listener.consume(sdk);