From e6aff92eec87ca19bd453d9138daa4ea2ceece19 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Mon, 5 Sep 2016 14:59:01 +0300 Subject: [PATCH 1/5] [platform] fixes a notification on patch download problems --- .../openapi/updateSettings/impl/UpdateInfoDialog.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfoDialog.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfoDialog.java index 3b9933f5d45c..ffff7c93c374 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfoDialog.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfoDialog.java @@ -138,6 +138,7 @@ class UpdateInfoDialog extends AbstractUpdateDialog { @Override public void actionPerformed(ActionEvent e) { + close(OK_EXIT_CODE); downloadPatchAndRestart(); } }); @@ -191,7 +192,7 @@ class UpdateInfoDialog extends AbstractUpdateDialog { command = UpdateInstaller.installPlatformUpdate(myPatch, myNewBuild.getNumber(), myForceHttps, indicator); } catch (Exception e) { - Logger.getInstance(UpdateChecker.class).warn(e); + Logger.getInstance(UpdateInstaller.class).warn(e); String title = IdeBundle.message("updates.error.connection.title"); String message = IdeBundle.message("update.downloading.patch.error", e.getMessage()); @@ -200,7 +201,7 @@ class UpdateInfoDialog extends AbstractUpdateDialog { protected void hyperlinkActivated(@NotNull Notification notification, @NotNull HyperlinkEvent e) { openDownloadPage(); } - }); + }).notify(null); return; } From 38a19cfe277b69b33c7636c37fcf8bf620196d20 Mon Sep 17 00:00:00 2001 From: Valentina Kiryushkina Date: Mon, 5 Sep 2016 15:27:54 +0300 Subject: [PATCH 2/5] Fix EDU-760 Font in Task Description does't change when editor font changes --- .../student/resources/code-mirror/template.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/educational-core/student/resources/code-mirror/template.html b/python/educational-core/student/resources/code-mirror/template.html index 86c239218f22..e7d2348fab7c 100644 --- a/python/educational-core/student/resources/code-mirror/template.html +++ b/python/educational-core/student/resources/code-mirror/template.html @@ -22,7 +22,7 @@ From a27346e0f95d77cf671e9785dda8da909d5102fa Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Mon, 5 Sep 2016 15:33:45 +0300 Subject: [PATCH 3/5] [platform] allows a manual patch application (IDEA-160700) --- .../application/impl/ApplicationImpl.java | 2 +- .../updateSettings/impl/UpdateInfoDialog.java | 34 +++++++++++++++++-- .../src/messages/IdeBundle.properties | 3 ++ 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java index af3aa527525c..ab72edb20b6b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java @@ -776,7 +776,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App exitCode = Restarter.scheduleRestart(beforeRestart); } catch (IOException e) { - LOG.warn("Cannot restart", e); + LOG.error("Cannot restart", e); } } System.exit(exitCode); diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfoDialog.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfoDialog.java index ffff7c93c374..0a1752574f86 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfoDialog.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfoDialog.java @@ -31,12 +31,15 @@ import com.intellij.openapi.application.impl.ApplicationImpl; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Task; +import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.BrowserHyperlinkListener; import com.intellij.ui.JBColor; import com.intellij.ui.LicensingFacade; import com.intellij.ui.components.JBLabel; +import com.intellij.util.SystemProperties; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.text.DateFormatUtil; import org.apache.http.client.utils.URIBuilder; @@ -52,6 +55,8 @@ import java.net.URISyntaxException; import java.util.Collection; import java.util.Date; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; import static com.intellij.openapi.util.Pair.pair; @@ -130,8 +135,9 @@ class UpdateInfoDialog extends AbstractUpdateDialog { protected Action[] createActions() { List actions = ContainerUtil.newArrayList(); - if (myPatch != null && ApplicationManager.getApplication().isRestartCapable()) { - actions.add(new AbstractAction(IdeBundle.message("updates.download.and.restart.button")) { + if (myPatch != null) { + boolean canRestart = ApplicationManager.getApplication().isRestartCapable(); + actions.add(new AbstractAction(IdeBundle.message(canRestart ? "updates.download.and.restart.button" : "updates.apply.manually.button")) { { setEnabled(!myWriteProtected); } @@ -213,7 +219,12 @@ class UpdateInfoDialog extends AbstractUpdateDialog { } ApplicationEx app = ApplicationManagerEx.getApplicationEx(); - app.invokeLater(() -> ((ApplicationImpl)app).exit(false, true, true, command)); + if (ApplicationManager.getApplication().isRestartCapable()) { + app.invokeLater(() -> ((ApplicationImpl)app).exit(false, true, true, command)); + } + else { + showPatchInstructions(command); + } } }.queue(); } @@ -224,6 +235,23 @@ class UpdateInfoDialog extends AbstractUpdateDialog { BrowserUtil.browse(augmentUrl(url)); } + private static void showPatchInstructions(String[] command) { + String product = ApplicationNamesInfo.getInstance().getLowercaseProductName(); + String version = ApplicationInfo.getInstance().getFullVersion(); + File file = new File(SystemProperties.getUserHome(), product + "-" + version + "-patch.txt"); + try { + String text = Stream.of(command).map(s -> s.indexOf(' ') > 0 ? '"' + s + '"' : s).collect(Collectors.joining(" ")); + FileUtil.writeToFile(file, text); + } + catch (Exception e) { + Logger.getInstance(UpdateInstaller.class).error(e); + return; + } + + String title = IdeBundle.message("update.notifications.title"), message = IdeBundle.message("update.apply.manually.message", file); + ApplicationManager.getApplication().invokeLater(() -> Messages.showInfoMessage(message, title)); + } + private static class ButtonAction extends AbstractAction { private final String myUrl; diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties index 5558ecd3a65d..7dc329625b60 100644 --- a/platform/platform-resources-en/src/messages/IdeBundle.properties +++ b/platform/platform-resources-en/src/messages/IdeBundle.properties @@ -929,6 +929,7 @@ updates.plugins.ready.header=Plugins from configured hosts are ready to updates.configure.label=To configure automatic update settings, see the Updates dialog of your IDE {0}. updates.incompatible.plugins.found={0,choice,1#Plugin|2#Plugins} incompatible with the new build found:{0,choice,1#' '|2#'
'} {1} updates.download.and.restart.button=Up&date and Restart +updates.apply.manually.button=Up&date Manually updates.more.info.button=&More Info... updates.ignore.update.button=&Ignore This Update updates.remind.later.button=&Remind Me Later @@ -966,6 +967,8 @@ update.sni.disabled.error=Secure connection is impossible with 'jsse.enableSNIEx update.sni.disabled.message=We wanted your IDE to receive upgrades over a secure connection. \ Unfortunately, this doesn't work with the 'jsse.enableSNIExtension' property set to 'false', so the option was disabled. \ You can enable it again in settings after setting the property to 'true'. +update.apply.manually.message=Unfortunately, the IDE is not capable of an automatic update on your system.\n \ + Please quit the IDE and apply the patch manually by invoking a command from this file:\n{0}. hierarchy.method.next.occurence.name=Go to next method hierarchy.method.prev.occurence.name=Go to previous method From aa6ae06c13b0da5261df14818cd7317639de9443 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Mon, 5 Sep 2016 15:50:05 +0300 Subject: [PATCH 4/5] Cleanup (restarter moved to platform) --- .../src/com/intellij/util/Restarter.java | 34 +++++++------------ 1 file changed, 12 insertions(+), 22 deletions(-) rename platform/{util => platform-impl}/src/com/intellij/util/Restarter.java (87%) diff --git a/platform/util/src/com/intellij/util/Restarter.java b/platform/platform-impl/src/com/intellij/util/Restarter.java similarity index 87% rename from platform/util/src/com/intellij/util/Restarter.java rename to platform/platform-impl/src/com/intellij/util/Restarter.java index 31aa77dcca41..ccb9fdc102f5 100644 --- a/platform/util/src/com/intellij/util/Restarter.java +++ b/platform/platform-impl/src/com/intellij/util/Restarter.java @@ -92,8 +92,7 @@ public class Restarter { } File restarter = new File(restartDir, "restarter.sh"); - BufferedWriter output = new BufferedWriter(new FileWriter(restarter)); - try { + try (BufferedWriter output = new BufferedWriter(new FileWriter(restarter))) { output.write("#!/bin/sh\n"); for (int i = 0; i < beforeRestart.length; i++) { output.write(beforeRestart[i]); @@ -102,16 +101,13 @@ public class Restarter { } output.write('\n'); } - finally { - output.close(); - } if (!restarter.setExecutable(true, true)) { throw new IOException("Cannot make file executable: " + restarter); } } - private static void restartOnWindows(@NotNull final String... beforeRestart) throws IOException { + private static void restartOnWindows(@NotNull String... beforeRestart) throws IOException { Kernel32 kernel32 = (Kernel32)Native.loadLibrary("kernel32", Kernel32.class); Shell32 shell32 = (Shell32)Native.loadLibrary("shell32", Shell32.class); @@ -121,14 +117,11 @@ public class Restarter { final String[] argv = getRestartArgv(argv_ptr.getWideStringArray(0, argc.getValue())); kernel32.LocalFree(argv_ptr); - doScheduleRestart(new File(PathManager.getBinPath(), "restarter.exe"), new Consumer>() { - @Override - public void consume(List commands) { - Collections.addAll(commands, String.valueOf(pid), String.valueOf(beforeRestart.length)); - Collections.addAll(commands, beforeRestart); - Collections.addAll(commands, String.valueOf(argv.length)); - Collections.addAll(commands, argv); - } + doScheduleRestart(new File(PathManager.getBinPath(), "restarter.exe"), commands -> { + Collections.addAll(commands, String.valueOf(pid), String.valueOf(beforeRestart.length)); + Collections.addAll(commands, beforeRestart); + Collections.addAll(commands, String.valueOf(argv.length)); + Collections.addAll(commands, argv); }); // Since the process ID is passed through the command line, we want to make sure that we don't exit before the "restarter" @@ -137,18 +130,15 @@ public class Restarter { TimeoutUtil.sleep(500); } - private static void restartOnMac(@NotNull final String... beforeRestart) throws IOException { + private static void restartOnMac(@NotNull String... beforeRestart) throws IOException { String homePath = PathManager.getHomePath(); int p = homePath.indexOf(".app"); if (p < 0) throw new IOException("Application bundle not found: " + homePath); final String bundlePath = homePath.substring(0, p + 4); - doScheduleRestart(new File(PathManager.getBinPath(), "restarter"), new Consumer>() { - @Override - public void consume(List commands) { - Collections.addAll(commands, bundlePath); - Collections.addAll(commands, beforeRestart); - } + doScheduleRestart(new File(PathManager.getBinPath(), "restarter"), commands -> { + Collections.addAll(commands, bundlePath); + Collections.addAll(commands, beforeRestart); }); } @@ -171,7 +161,7 @@ public class Restarter { } private static void doScheduleRestart(File restarterFile, Consumer> argumentsBuilder) throws IOException { - List commands = new ArrayList(); + List commands = new ArrayList<>(); commands.add(createTempExecutable(restarterFile).getPath()); argumentsBuilder.consume(commands); Runtime.getRuntime().exec(ArrayUtil.toStringArray(commands)); From 507b49947f4b7768af7b4926b07f027feb17ddd7 Mon Sep 17 00:00:00 2001 From: Alexander Kass Date: Mon, 5 Sep 2016 16:03:53 +0300 Subject: [PATCH 5/5] Pass editor to release when releasing deferred --- .../src/com/intellij/ui/EditorTextField.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ui/EditorTextField.java b/platform/platform-impl/src/com/intellij/ui/EditorTextField.java index df24e0817cc2..6a07c6408f0d 100644 --- a/platform/platform-impl/src/com/intellij/ui/EditorTextField.java +++ b/platform/platform-impl/src/com/intellij/ui/EditorTextField.java @@ -220,7 +220,7 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener, boolean isFocused = isFocusOwner(); EditorEx newEditor = createEditor(); - releaseEditor(); + releaseEditor(myEditor); myEditor = newEditor; add(myEditor.getComponent(), BorderLayout.CENTER); @@ -331,7 +331,7 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener, ProjectManagerListener listener = new ProjectManagerListener() { @Override public void projectClosing(Project project) { - releaseEditor(); + releaseEditor(myEditor); } }; ProjectManager.getInstance().addProjectManagerListener(myProject, listener); @@ -374,11 +374,8 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener, Disposer.dispose(myDisposable); } - private void releaseEditor() { - if (myEditor == null) return; - - final Editor editor = myEditor; - myEditor = null; + private void releaseEditor(Editor editor) { + if (editor == null) return; // todo IMHO this should be removed completely if (myProject != null && !myProject.isDisposed() && myIsViewer) { @@ -403,7 +400,9 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener, // removeNotify(), so we need to let swing complete its removeNotify() chain // and only then execute another removal from the hierarchy. Otherwise // swing goes nuts because of nested removals and indices get corrupted - SwingUtilities.invokeLater(this::releaseEditor); + EditorEx editor = myEditor; + SwingUtilities.invokeLater(() -> releaseEditor(editor)); + myEditor = null; } @Override @@ -581,7 +580,7 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener, setViewerEnabled(enabled); EditorEx editor = myEditor; if (editor != null) { - releaseEditor(); + releaseEditor(editor); initEditor(); revalidate(); } @@ -654,7 +653,8 @@ public class EditorTextField extends NonOpaquePanel implements DocumentListener, } if (toReleaseEditor) { - releaseEditor(); + releaseEditor(myEditor); + myEditor = null; myPassivePreferredSize = size; }