[platform] environment-based lookup for (Unix) utilities (IDEA-164810)

This commit is contained in:
Roman Shevchenko
2016-12-01 13:15:59 +01:00
parent 676e9060a8
commit dc730e866d
5 changed files with 104 additions and 41 deletions
@@ -23,6 +23,7 @@ import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.util.NotNullLazyValue;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.PathExecLazyValue;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.util.containers.ContainerUtil;
@@ -36,26 +37,12 @@ import java.util.List;
import java.util.Map;
public class ExecUtil {
private static class ExecutableExistsLazyValue extends NotNullLazyValue<Boolean> {
private final String myPathname;
public ExecutableExistsLazyValue(String pathname) {
myPathname = pathname;
}
@NotNull
@Override
protected Boolean compute() {
return new File(myPathname).canExecute();
}
}
private static final NotNullLazyValue<Boolean> hasGkSudo = new ExecutableExistsLazyValue("/usr/bin/gksudo");
private static final NotNullLazyValue<Boolean> hasKdeSudo = new ExecutableExistsLazyValue("/usr/bin/kdesudo");
private static final NotNullLazyValue<Boolean> hasPkExec = new ExecutableExistsLazyValue("/usr/bin/pkexec");
private static final NotNullLazyValue<Boolean> hasGnomeTerminal = new ExecutableExistsLazyValue("/usr/bin/gnome-terminal");
private static final NotNullLazyValue<Boolean> hasKdeTerminal = new ExecutableExistsLazyValue("/usr/bin/konsole");
private static final NotNullLazyValue<Boolean> hasXTerm = new ExecutableExistsLazyValue("/usr/bin/xterm");
private static final NotNullLazyValue<Boolean> hasGkSudo = new PathExecLazyValue("gksudo");
private static final NotNullLazyValue<Boolean> hasKdeSudo = new PathExecLazyValue("kdesudo");
private static final NotNullLazyValue<Boolean> hasPkExec = new PathExecLazyValue("pkexec");
private static final NotNullLazyValue<Boolean> hasGnomeTerminal = new PathExecLazyValue("gnome-terminal");
private static final NotNullLazyValue<Boolean> hasKdeTerminal = new PathExecLazyValue("konsole");
private static final NotNullLazyValue<Boolean> hasXTerm = new PathExecLazyValue("xterm");
private ExecUtil() { }
@@ -236,15 +223,15 @@ public class ExecUtil {
return Arrays.asList(getOpenCommandPath(), "-a", "Terminal", command);
}
else if (hasKdeTerminal.getValue()) {
return Arrays.asList("/usr/bin/konsole", "-e", command);
return Arrays.asList("konsole", "-e", command);
}
else if (hasGnomeTerminal.getValue()) {
return title != null ? Arrays.asList("/usr/bin/gnome-terminal", "-t", title, "-x", command)
: Arrays.asList("/usr/bin/gnome-terminal", "-x", command);
return title != null ? Arrays.asList("gnome-terminal", "-t", title, "-x", command)
: Arrays.asList("gnome-terminal", "-x", command);
}
else if (hasXTerm.getValue()) {
return title != null ? Arrays.asList("/usr/bin/xterm", "-T", title, "-e", command)
: Arrays.asList("/usr/bin/xterm", "-e", command);
return title != null ? Arrays.asList("xterm", "-T", title, "-e", command)
: Arrays.asList("xterm", "-e", command);
}
throw new UnsupportedOperationException("Unsupported OS/desktop: " + SystemInfo.OS_NAME + '/' + SystemInfo.SUN_DESKTOP);
@@ -295,7 +295,7 @@ public class ShowFilePathAction extends AnAction {
});
}
else if (SystemInfo.hasXdgOpen()) {
GeneralCommandLine cmd = new GeneralCommandLine("/usr/bin/xdg-open", dir);
GeneralCommandLine cmd = new GeneralCommandLine("xdg-open", dir);
ExecUtil.execAndGetOutput(cmd).checkSuccess(LOG);
}
else if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.OPEN)) {
@@ -16,13 +16,13 @@
package com.intellij.openapi.util;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.PathExecLazyValue;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.SystemProperties;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
@@ -112,24 +112,12 @@ public class SystemInfo extends SystemInfoRt {
public static final boolean is64Bit = !is32Bit;
public static final boolean isMacIntel64 = isMac && "x86_64".equals(OS_ARCH);
private static final NotNullLazyValue<Boolean> ourHasXdgOpen = new AtomicNotNullLazyValue<Boolean>() {
@NotNull
@Override
protected Boolean compute() {
return new File("/usr/bin/xdg-open").canExecute();
}
};
private static final NotNullLazyValue<Boolean> ourHasXdgOpen = new PathExecLazyValue("xdg-open");
public static boolean hasXdgOpen() {
return isXWindow && ourHasXdgOpen.getValue();
}
private static final NotNullLazyValue<Boolean> ourHasXdgMime = new AtomicNotNullLazyValue<Boolean>() {
@NotNull
@Override
protected Boolean compute() {
return new File("/usr/bin/xdg-mime").canExecute();
}
};
private static final NotNullLazyValue<Boolean> ourHasXdgMime = new PathExecLazyValue("xdg-mime");
public static boolean hasXdgMime() {
return isXWindow && ourHasXdgMime.getValue();
}
@@ -0,0 +1,50 @@
/*
* Copyright 2000-2016 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.intellij.openapi.util.io;
import com.intellij.openapi.util.AtomicNotNullLazyValue;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.EnvironmentUtil;
import org.jetbrains.annotations.NotNull;
import java.io.File;
public class PathExecLazyValue extends AtomicNotNullLazyValue<Boolean> {
private final String myName;
public PathExecLazyValue(@NotNull String name) {
if (StringUtil.containsAnyChar(name, "/\\")) {
throw new IllegalArgumentException(name);
}
myName = name;
}
@NotNull
@Override
protected Boolean compute() {
String path = EnvironmentUtil.getValue(SystemInfo.isWindows ? "Path" : "PATH");
if (path != null) {
for (String dir : StringUtil.tokenize(path, File.pathSeparator)) {
if (new File(dir, myName).canExecute()) {
return true;
}
}
}
return false;
}
}
@@ -0,0 +1,38 @@
/*
* Copyright 2000-2016 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.intellij.openapi.util.io
import com.intellij.openapi.util.SystemInfo
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test
import java.io.File
class PathExecLazyValueTest {
@Test fun positive() {
val shell = File(if (SystemInfo.isWindows) "C:\\Windows\\System32\\cmd.exe" else "/bin/sh")
assertTrue(shell.canExecute())
assertTrue(PathExecLazyValue(shell.name).value)
}
@Test fun negative() {
assertFalse(PathExecLazyValue("no-one-in-his-right-mind-names-an-exec-like-this").value)
}
@Test(expected = IllegalArgumentException::class) fun contract() {
PathExecLazyValue("bad\\path")
}
}