mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
New package operation failure dialog
This commit is contained in:
@@ -20,23 +20,18 @@ import com.intellij.execution.process.ProcessOutput;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author vlan
|
||||
*/
|
||||
public class PyExecutionException extends ExecutionException {
|
||||
private static final Pattern WITH_CR_DELIMITER_PATTERN = Pattern.compile("(?<=\r|\n|\r\n)");
|
||||
|
||||
@NotNull private String myCommand;
|
||||
@NotNull private List<String> myArgs;
|
||||
@NotNull private final String myStdout;
|
||||
@NotNull private final String myStderr;
|
||||
private final int myExitCode;
|
||||
@NotNull private String myMessage;
|
||||
@NotNull private final List<? extends PyExecutionFix> myFixes;
|
||||
|
||||
public PyExecutionException(@NotNull String message, @NotNull String command, @NotNull List<String> args) {
|
||||
@@ -56,7 +51,6 @@ public class PyExecutionException extends ExecutionException {
|
||||
myStdout = stdout;
|
||||
myStderr = stderr;
|
||||
myExitCode = exitCode;
|
||||
myMessage = stripLinesWithoutLineFeeds(message);
|
||||
myFixes = fixes;
|
||||
}
|
||||
|
||||
@@ -84,23 +78,6 @@ public class PyExecutionException extends ExecutionException {
|
||||
return myArgs;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getMessage() {
|
||||
return myMessage;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String stripLinesWithoutLineFeeds(@NotNull String s) {
|
||||
final String[] lines = WITH_CR_DELIMITER_PATTERN.split(s);
|
||||
final List<String> result = new ArrayList<String>();
|
||||
for (String line : lines) {
|
||||
if (!line.endsWith("\r")) {
|
||||
result.add(line);
|
||||
}
|
||||
}
|
||||
return StringUtil.join(result, "");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<? extends PyExecutionFix> getFixes() {
|
||||
return myFixes;
|
||||
|
||||
@@ -488,15 +488,10 @@ public class PyPackageManagerImpl extends PyPackageManager {
|
||||
if (result.isCancelled()) {
|
||||
throw new RunCanceledByUserException();
|
||||
}
|
||||
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.";
|
||||
}
|
||||
final int exitCode = result.getExitCode();
|
||||
if (exitCode != 0) {
|
||||
final String message = StringUtil.isEmptyOrSpaces(result.getStdout()) && StringUtil.isEmptyOrSpaces(result.getStderr()) ?
|
||||
"Permission denied" : "Non-zero exit code";
|
||||
throw new PyExecutionException(message, helperPath, args, result);
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -33,18 +33,22 @@ import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.webcore.packaging.PackagesNotificationPanel;
|
||||
import com.jetbrains.python.packaging.ui.PyPackageNotificationDialog;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author vlan
|
||||
*/
|
||||
public class PyPackageManagerUI {
|
||||
private static final Logger LOG = Logger.getInstance(PyPackageManagerUI.class);
|
||||
@NotNull private static final Logger LOG = Logger.getInstance(PyPackageManagerUI.class);
|
||||
@NotNull private static final Pattern PATTERN_ERROR_LINE = Pattern.compile(".*error:.*", Pattern.CASE_INSENSITIVE);
|
||||
|
||||
@Nullable private Listener myListener;
|
||||
@NotNull private Project myProject;
|
||||
@NotNull private Sdk mySdk;
|
||||
@@ -55,6 +59,33 @@ public class PyPackageManagerUI {
|
||||
void finished(List<ExecutionException> exceptions);
|
||||
}
|
||||
|
||||
public static class ExecutionFailure {
|
||||
@NotNull private final String myMessage;
|
||||
@Nullable private final String myCommand;
|
||||
@Nullable private final String myOutput;
|
||||
|
||||
public ExecutionFailure(@NotNull String message, @Nullable String command, @Nullable String output) {
|
||||
myMessage = message;
|
||||
myCommand = command;
|
||||
myOutput = output;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getMessage() {
|
||||
return myMessage;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getCommand() {
|
||||
return myCommand;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getOutput() {
|
||||
return myOutput;
|
||||
}
|
||||
}
|
||||
|
||||
public PyPackageManagerUI(@NotNull Project project, @NotNull Sdk sdk, @Nullable Listener listener) {
|
||||
myProject = project;
|
||||
mySdk = sdk;
|
||||
@@ -184,8 +215,8 @@ public class PyPackageManagerUI {
|
||||
NotificationType.INFORMATION));
|
||||
}
|
||||
else if (!isCancelled(exceptions)) {
|
||||
final ExecutionFailure failure = analyzeException(exceptions.get(0));
|
||||
final String firstLine = getTitle() + ": error occurred.";
|
||||
final String description = createDescription(exceptions, firstLine);
|
||||
notificationRef.set(new Notification(PACKAGING_GROUP_ID, getFailureTitle(),
|
||||
firstLine + " <a href=\"xxx\">Details...</a>",
|
||||
NotificationType.ERROR,
|
||||
@@ -194,7 +225,9 @@ public class PyPackageManagerUI {
|
||||
public void hyperlinkUpdate(@NotNull Notification notification,
|
||||
@NotNull HyperlinkEvent event) {
|
||||
assert myProject != null;
|
||||
PackagesNotificationPanel.showError(myProject, getFailureTitle(), description);
|
||||
final String title = StringUtil.capitalizeWords(getFailureTitle(), true);
|
||||
final PyPackageNotificationDialog dialog = new PyPackageNotificationDialog(title, failure);
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
));
|
||||
@@ -386,4 +419,28 @@ public class PyPackageManagerUI {
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static ExecutionFailure analyzeException(@NotNull ExecutionException e) {
|
||||
if (e instanceof PyExecutionException) {
|
||||
final PyExecutionException ee = (PyExecutionException)e;
|
||||
final String stdoutCause = findErrorCause(ee.getStdout());
|
||||
final String stderrCause = findErrorCause(ee.getStderr());
|
||||
final String message = stdoutCause != null ? stdoutCause : stderrCause != null ? stderrCause : ee.getMessage();
|
||||
return new ExecutionFailure(message, ee.getCommand() + " " + StringUtil.join(ee.getArgs(), " "), ee.getStdout());
|
||||
}
|
||||
else {
|
||||
return new ExecutionFailure(e.getMessage(), null, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String findErrorCause(@NotNull String output) {
|
||||
final Matcher m = PATTERN_ERROR_LINE.matcher(output);
|
||||
if (m.find()) {
|
||||
final String result = m.group();
|
||||
return result != null ? result.trim() : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.jetbrains.python.packaging.ui.PyPackageNotificationDialog">
|
||||
<grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="604" height="929"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<vspacer id="de4c">
|
||||
<constraints>
|
||||
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
<grid id="a16a8" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="294" class="com.intellij.ui.components.JBLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Error occurred:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="23f72" class="com.intellij.ui.components.JBLabel" binding="myErrorMessage">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="2" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<foreground color="-4511744"/>
|
||||
<text value="Unknown error"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
<grid id="8cad" binding="myCommandOutputPanel" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="4e743" class="com.intellij.ui.components.JBLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<labelFor value="6fb53"/>
|
||||
<text value="Command output:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<scrollpane id="6fb53" class="com.intellij.ui.components.JBScrollPane">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="9" fill="0" indent="2" use-parent-layout="false">
|
||||
<preferred-size width="700" height="300"/>
|
||||
<maximum-size width="700" height="300"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="307b8" class="javax.swing.JTextArea" binding="myCommandOutput">
|
||||
<constraints/>
|
||||
<properties>
|
||||
<editable value="false"/>
|
||||
<text value="No output"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</scrollpane>
|
||||
</children>
|
||||
</grid>
|
||||
<grid id="4cbff" binding="myCommandPanel" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="2e7d0" class="com.intellij.ui.components.JBLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Executed command:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<scrollpane id="c24f2" class="com.intellij.ui.components.JBScrollPane">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="9" fill="0" indent="2" use-parent-layout="false">
|
||||
<preferred-size width="700" height="60"/>
|
||||
<maximum-size width="700" height="60"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
<properties>
|
||||
<verticalScrollBarPolicy value="21"/>
|
||||
</properties>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="fb0fa" class="javax.swing.JTextArea" binding="myCommand">
|
||||
<constraints/>
|
||||
<properties>
|
||||
<editable value="false"/>
|
||||
<text value="None"/>
|
||||
</properties>
|
||||
</component>
|
||||
</children>
|
||||
</scrollpane>
|
||||
</children>
|
||||
</grid>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.jetbrains.python.packaging.ui;
|
||||
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
import com.jetbrains.python.packaging.PyPackageManagerUI;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* @author vlan
|
||||
*/
|
||||
public class PyPackageNotificationDialog extends DialogWrapper {
|
||||
private JPanel myMainPanel;
|
||||
private JBLabel myErrorMessage;
|
||||
private JTextArea myCommand;
|
||||
private JTextArea myCommandOutput;
|
||||
private JPanel myCommandOutputPanel;
|
||||
private JPanel myCommandPanel;
|
||||
|
||||
public PyPackageNotificationDialog(@NotNull String title, @NotNull PyPackageManagerUI.ExecutionFailure failure) {
|
||||
super(false);
|
||||
init();
|
||||
setResizable(false);
|
||||
setTitle(title);
|
||||
final String command = failure.getCommand();
|
||||
final String output = failure.getOutput();
|
||||
final String message = failure.getMessage();
|
||||
|
||||
myCommandPanel.setVisible(command != null);
|
||||
myCommandOutputPanel.setVisible(output != null);
|
||||
|
||||
myErrorMessage.setText(message);
|
||||
if (command != null) {
|
||||
myCommand.setText(command);
|
||||
}
|
||||
if (output != null) {
|
||||
myCommandOutput.setText(output);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected JComponent createCenterPanel() {
|
||||
return myMainPanel;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user