backport: 16.1.3
This commit is contained in:
parent
560653fd47
commit
62d3771a75
8 changed files with 160 additions and 59 deletions
|
@ -17,6 +17,15 @@ Changelog structure reference:
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
## [16.1.3]
|
||||
|
||||
### Changed
|
||||
|
||||
- Debugger (Windows)
|
||||
- MSVC debugger metadata download now requires consent from the user
|
||||
- Metadata download is now cached after the first fetch
|
||||
- Metadata download timeout has been set to 3 seconds, after which it reverts to the fallback file
|
||||
|
||||
## [16.1.2]
|
||||
|
||||
### Fixed
|
||||
|
|
|
@ -11,7 +11,7 @@ baseIDE=clion
|
|||
ideaVersion=2024.1.4
|
||||
clionVersion=2024.1.4
|
||||
|
||||
pluginVersion=16.1.2
|
||||
pluginVersion=16.1.3
|
||||
|
||||
# Gradle Releases -> https://github.com/gradle/gradle/releases
|
||||
gradleVersion=8.9
|
||||
|
|
|
@ -13,7 +13,7 @@ notification.nativedebug.browser=Open in Browser
|
|||
notification.title.debugger=Debugger
|
||||
notification.content.debugger.successfully.downloaded=Debugger successfully downloaded
|
||||
notification.content.debugger.downloading.failed=Debugger downloading failed
|
||||
notification.content.debugger.metadata.downloading.failed=Debugger metadata downloading failed
|
||||
notification.content.debugger.metadata.downloading.failed=Debugger metadata downloading failed, switching to fallback
|
||||
notification.content.debugger.metadata.fallback.fetch.failed=Debugger fallback metadata fetch failed
|
||||
notification.content.debugger.metadata.fallback.parse.failed=Debugger fallback metadata parse failed
|
||||
settings.debugger.toolchain.download.debugger.automatically.checkbox=Download and update the debugger automatically
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
package com.falsepattern.zigbrains.debugger.settings;
|
||||
|
||||
public enum MSVCDownloadPermission {
|
||||
AskMe,
|
||||
Allow,
|
||||
Deny
|
||||
}
|
|
@ -22,6 +22,7 @@ public class ZigDebuggerSettings extends XDebuggerSettings<ZigDebuggerSettings>
|
|||
|
||||
public boolean downloadAutomatically = false;
|
||||
public boolean useClion = true;
|
||||
public MSVCDownloadPermission msvcConsent = MSVCDownloadPermission.AskMe;
|
||||
|
||||
protected ZigDebuggerSettings() {
|
||||
super("Zig");
|
||||
|
|
|
@ -10,6 +10,7 @@ import com.intellij.openapi.extensions.PluginId;
|
|||
import com.intellij.openapi.observable.util.ListenerUiUtil;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.ui.ComboBox;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.ui.components.JBCheckBox;
|
||||
import lombok.val;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
@ -79,7 +80,7 @@ public class ZigDebuggerToolchainConfigurableUi extends ZigDebuggerUiComponent {
|
|||
panel.row(r -> {
|
||||
r.cell(downloadAutomaticallyCheckBox);
|
||||
});
|
||||
if (PluginManager.isPluginInstalled(PluginId.getId("com.intellij.modules.clion"))) {
|
||||
if (PluginManager.isPluginInstalled(PluginId.getId("com.intellij.modules.clion")) && !SystemInfo.isWindows) {
|
||||
panel.row(r -> {
|
||||
r.cell(useClion);
|
||||
});
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
package com.falsepattern.zigbrains.debugger.toolchain;
|
||||
|
||||
import com.falsepattern.zigbrains.ZigBundle;
|
||||
import com.falsepattern.zigbrains.debugger.settings.MSVCDownloadPermission;
|
||||
import com.falsepattern.zigbrains.debugger.settings.ZigDebuggerSettings;
|
||||
import com.intellij.notification.Notification;
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.notification.Notifications;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.ui.DialogBuilder;
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
import com.intellij.ui.components.JBPanel;
|
||||
import com.intellij.util.download.DownloadableFileService;
|
||||
import lombok.Cleanup;
|
||||
import lombok.val;
|
||||
|
||||
import javax.swing.BoxLayout;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static com.falsepattern.zigbrains.debugger.toolchain.ZigDebuggerToolchainService.downloadPath;
|
||||
|
||||
class MSVCMetadataProvider {
|
||||
private Properties cached;
|
||||
private Future<Properties> downloadMSVCProps() {
|
||||
val future = new CompletableFuture<Properties>();
|
||||
ApplicationManager.getApplication().executeOnPooledThread(() -> {
|
||||
try {
|
||||
val service = DownloadableFileService.getInstance();
|
||||
val desc = service.createFileDescription("https://falsepattern.com/zigbrains/msvc.properties", "msvc.properties");
|
||||
val downloader = service.createDownloader(List.of(desc), "Debugger metadata downloading");
|
||||
val downloadDirectory = downloadPath().toFile();
|
||||
val prop = new Properties();
|
||||
val downloadResults = downloader.download(downloadDirectory);
|
||||
for (val result : downloadResults) {
|
||||
if (Objects.equals(result.second.getDefaultFileName(), "msvc.properties")) {
|
||||
@Cleanup val reader = new FileReader(result.first);
|
||||
prop.load(reader);
|
||||
}
|
||||
}
|
||||
future.complete(prop);
|
||||
} catch (Throwable t) {
|
||||
future.completeExceptionally(t);
|
||||
}
|
||||
});
|
||||
return future;
|
||||
}
|
||||
|
||||
private Properties fetchBuiltinMSVCProps() {
|
||||
val prop = new Properties();
|
||||
try {
|
||||
@Cleanup val resource = ZigDebuggerToolchainService.class.getResourceAsStream("/msvc.properties");
|
||||
if (resource == null) {
|
||||
Notifications.Bus.notify(new Notification(
|
||||
"ZigBrains.Debugger.Error",
|
||||
ZigBundle.message("notification.title.debugger"),
|
||||
ZigBundle.message("notification.content.debugger.metadata.fallback.fetch.failed"),
|
||||
NotificationType.ERROR
|
||||
));
|
||||
return prop;
|
||||
}
|
||||
val reader = new InputStreamReader(resource);
|
||||
prop.load(reader);
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
Notifications.Bus.notify(new Notification(
|
||||
"ZigBrains.Debugger.Error",
|
||||
ZigBundle.message("notification.title.debugger"),
|
||||
ZigBundle.message("notification.content.debugger.metadata.fallback.parse.failed"),
|
||||
NotificationType.ERROR
|
||||
));
|
||||
}
|
||||
return prop;
|
||||
}
|
||||
|
||||
|
||||
Properties msvcProperties() {
|
||||
if (cached != null)
|
||||
return cached;
|
||||
val settings = ZigDebuggerSettings.getInstance();
|
||||
var permission = settings.msvcConsent;
|
||||
if (permission == MSVCDownloadPermission.AskMe) {
|
||||
AtomicReference<Boolean> accepted = new AtomicReference<>(false);
|
||||
ApplicationManager.getApplication().invokeAndWait(() -> {
|
||||
val dialog = new DialogBuilder();
|
||||
dialog.setTitle("Network Request Consent");
|
||||
dialog.addCancelAction().setText("Deny");
|
||||
dialog.addOkAction().setText("Allow");
|
||||
val centerPanel = new JBPanel<>();
|
||||
centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.Y_AXIS));
|
||||
centerPanel.add(new JBLabel("ZigBrains needs to download some metadata from the internet for debugging on Windows."));
|
||||
centerPanel.add(new JBLabel("ZigBrains will use the fallback metadata shipped inside the plugin if the request is denied."));
|
||||
centerPanel.add(new JBLabel("Would you like to allow this network request?"));
|
||||
dialog.centerPanel(centerPanel);
|
||||
accepted.set(dialog.showAndGet());
|
||||
});
|
||||
permission = settings.msvcConsent = accepted.get() ? MSVCDownloadPermission.Allow : MSVCDownloadPermission.Deny;
|
||||
}
|
||||
return switch (permission) {
|
||||
//noinspection DataFlowIssue
|
||||
case AskMe, Deny -> cached = fetchBuiltinMSVCProps();
|
||||
case Allow -> {
|
||||
val future = downloadMSVCProps();
|
||||
try {
|
||||
yield future.get(3, TimeUnit.SECONDS);
|
||||
} catch (ExecutionException | InterruptedException | TimeoutException e) {
|
||||
e.printStackTrace();
|
||||
Notifications.Bus.notify(new Notification(
|
||||
"ZigBrains.Debugger.Error",
|
||||
ZigBundle.message("notification.title.debugger"),
|
||||
ZigBundle.message("notification.content.debugger.metadata.downloading.failed"),
|
||||
NotificationType.ERROR
|
||||
));
|
||||
settings.msvcConsent = MSVCDownloadPermission.Deny;
|
||||
yield cached = fetchBuiltinMSVCProps();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -2,6 +2,8 @@ package com.falsepattern.zigbrains.debugger.toolchain;
|
|||
|
||||
import com.falsepattern.zigbrains.ZigBundle;
|
||||
import com.falsepattern.zigbrains.common.ZigPathManager;
|
||||
import com.falsepattern.zigbrains.debugger.settings.MSVCDownloadPermission;
|
||||
import com.falsepattern.zigbrains.debugger.settings.ZigDebuggerSettings;
|
||||
import com.intellij.notification.Notification;
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.notification.Notifications;
|
||||
|
@ -15,6 +17,7 @@ import com.intellij.openapi.util.SystemInfo;
|
|||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.ui.BrowserHyperlinkListener;
|
||||
import com.intellij.ui.HyperlinkLabel;
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
import com.intellij.ui.components.JBPanel;
|
||||
import com.intellij.util.download.DownloadableFileService;
|
||||
import com.intellij.util.io.Decompressor;
|
||||
|
@ -24,17 +27,13 @@ import com.jetbrains.cidr.execution.debugger.CidrDebuggerPathManager;
|
|||
import com.jetbrains.cidr.execution.debugger.backend.bin.UrlProvider;
|
||||
import com.jetbrains.cidr.execution.debugger.backend.lldb.LLDBDriverConfiguration;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Cleanup;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.val;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
@ -43,10 +42,14 @@ import java.util.Arrays;
|
|||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@Service(Service.Level.APP)
|
||||
public final class ZigDebuggerToolchainService {
|
||||
private MSVCMetadataProvider msvcProvider = new MSVCMetadataProvider();
|
||||
public static ZigDebuggerToolchainService getInstance() {
|
||||
return ApplicationManager.getApplication().getService(ZigDebuggerToolchainService.class);
|
||||
}
|
||||
|
@ -320,7 +323,7 @@ public final class ZigDebuggerToolchainService {
|
|||
};
|
||||
}
|
||||
|
||||
private static Path downloadPath() {
|
||||
static Path downloadPath() {
|
||||
return Paths.get(PathManager.getTempPath());
|
||||
}
|
||||
|
||||
|
@ -354,56 +357,6 @@ public final class ZigDebuggerToolchainService {
|
|||
return UrlProvider.gdb(OS.CURRENT, CpuArch.CURRENT);
|
||||
}
|
||||
|
||||
private Properties msvcProperties() {
|
||||
val service = DownloadableFileService.getInstance();
|
||||
val desc = service.createFileDescription("https://falsepattern.com/zigbrains/msvc.properties", "msvc.properties");
|
||||
val downloader = service.createDownloader(List.of(desc), "Debugger metadata downloading");
|
||||
val downloadDirectory = downloadPath().toFile();
|
||||
val prop = new Properties();
|
||||
try {
|
||||
val downloadResults = downloader.download(downloadDirectory);
|
||||
for (val result : downloadResults) {
|
||||
if (Objects.equals(result.second.getDefaultFileName(), "msvc.properties")) {
|
||||
@Cleanup val reader = new FileReader(result.first);
|
||||
prop.load(reader);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
//TODO logging
|
||||
e.printStackTrace();
|
||||
Notifications.Bus.notify(new Notification(
|
||||
"ZigBrains.Debugger.Error",
|
||||
ZigBundle.message("notification.title.debugger"),
|
||||
ZigBundle.message("notification.content.debugger.metadata.downloading.failed"),
|
||||
NotificationType.ERROR
|
||||
));
|
||||
//Try to load fallback file
|
||||
try {
|
||||
@Cleanup val resource = ZigDebuggerToolchainService.class.getResourceAsStream("msvc.properties");
|
||||
if (resource == null) {
|
||||
Notifications.Bus.notify(new Notification(
|
||||
"ZigBrains.Debugger.Error",
|
||||
ZigBundle.message("notification.title.debugger"),
|
||||
ZigBundle.message("notification.content.debugger.metadata.fallback.fetch.failed"),
|
||||
NotificationType.ERROR
|
||||
));
|
||||
return prop;
|
||||
}
|
||||
val reader = new InputStreamReader(resource);
|
||||
prop.load(reader);
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
Notifications.Bus.notify(new Notification(
|
||||
"ZigBrains.Debugger.Error",
|
||||
ZigBundle.message("notification.title.debugger"),
|
||||
ZigBundle.message("notification.content.debugger.metadata.fallback.parse.failed"),
|
||||
NotificationType.ERROR
|
||||
));
|
||||
}
|
||||
}
|
||||
return prop;
|
||||
}
|
||||
|
||||
private MSVCUrl msvcUrl() {
|
||||
String dlKey = switch (CpuArch.CURRENT) {
|
||||
case X86 -> "downloadX86";
|
||||
|
@ -414,7 +367,7 @@ public final class ZigDebuggerToolchainService {
|
|||
if (dlKey == null)
|
||||
return null;
|
||||
|
||||
val props = msvcProperties();
|
||||
val props = msvcProvider.msvcProperties();
|
||||
val version = props.getProperty("version");
|
||||
val url = props.getProperty(dlKey);
|
||||
if (url == null || version == null)
|
||||
|
|
Loading…
Add table
Reference in a new issue