diff --git a/src/main/kotlin/com/carbonblack/intellij/rpmmacro/RpmMacroUtil.kt b/src/main/kotlin/com/carbonblack/intellij/rpmmacro/RpmMacroUtil.kt index 733b273..fd7a45a 100644 --- a/src/main/kotlin/com/carbonblack/intellij/rpmmacro/RpmMacroUtil.kt +++ b/src/main/kotlin/com/carbonblack/intellij/rpmmacro/RpmMacroUtil.kt @@ -2,6 +2,7 @@ package com.carbonblack.intellij.rpmmacro import com.carbonblack.intellij.rpmmacro.psi.RpmMacroFile import com.carbonblack.intellij.rpmmacro.psi.RpmMacroMacro +import com.carbonblack.intellij.rpmspec.RpmSpecSettingsState import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.LocalFileSystem @@ -25,10 +26,9 @@ import kotlin.streams.asSequence private val log = Logger.getInstance(RpmMacroUtil::class.java) -private fun String.runCommand(workingDir: File? = null, action: (String) -> Unit) { - val parts = this.split("\\s".toRegex()) +private fun List.runCommand(workingDir: File? = null, action: (String) -> Unit) { val proc = ProcessBuilder() - .command(parts) + .command(this) .directory(workingDir) .redirectErrorStream(true) .start() @@ -92,7 +92,7 @@ object RpmMacroUtil { val pathsRegex = Regex("^Macro path: (.*)$") val targetRegex = Regex("^\\S+:\\s+_target\\s+(.*)$") - "rpm --showrc".runCommand { line -> + listOf(RpmSpecSettingsState.instance.rpmCommandPath, "--showrc").runCommand { line -> if (paths.isEmpty()) { pathsRegex.find(line)?.groups?.get(1)?.let { match -> paths += match.value.split(":") diff --git a/src/main/kotlin/com/carbonblack/intellij/rpmspec/RpmSpecSettingsConfigurable.kt b/src/main/kotlin/com/carbonblack/intellij/rpmspec/RpmSpecSettingsConfigurable.kt new file mode 100644 index 0000000..eb1a1bf --- /dev/null +++ b/src/main/kotlin/com/carbonblack/intellij/rpmspec/RpmSpecSettingsConfigurable.kt @@ -0,0 +1,67 @@ +package com.carbonblack.intellij.rpmspec + +import com.carbonblack.intellij.rpmmacro.RpmMacroUtil +import com.intellij.openapi.options.Configurable +import com.intellij.ui.IdeBorderFactory +import com.intellij.ui.components.JBList +import com.intellij.ui.components.JBScrollPane +import com.intellij.ui.components.JBTextField +import com.intellij.util.ui.FormBuilder +import java.awt.BorderLayout +import java.awt.Insets +import javax.swing.* +import kotlin.reflect.KProperty + +private class TextFieldDelegate(private val textField: JBTextField) { + operator fun getValue(thisRef: Any?, property: KProperty<*>): String { + return textField.text + } + + operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) { + textField.text = value + } +} + +class RpmSpecSettingsConfigurable : Configurable { + override fun getDisplayName() = "RPM SPEC File" + override fun getPreferredFocusedComponent(): JComponent = rpmCommandPathBox + + private val rpmCommandPathBox = JBTextField("rpm") + private var rpmCommandPath: String by TextFieldDelegate(rpmCommandPathBox) + + private val detectedPathsList = JBList().apply { + selectionMode = ListSelectionModel.SINGLE_SELECTION + border = IdeBorderFactory.createEmptyBorder(Insets(0, 3, 0, 0)) + isFocusable = false + } + + override fun createComponent(): JComponent { + val detectedMacrosPanel = JPanel(BorderLayout()).apply { + // This is for if we decide to make the list of macros editable + /* val toolbarDecorator = ToolbarDecorator.createDecorator(detectedPathsList) + .setScrollPaneBorder(JBUI.Borders.empty()) + .setPanelBorder(JBUI.Borders.customLine(JBColor.border(), 0, 1, 0, 1)) + add(toolbarDecorator.createPanel(), BorderLayout.NORTH) */ + add(JBScrollPane(detectedPathsList), BorderLayout.CENTER) + border = IdeBorderFactory.createTitledBorder("Detected Macro Files:", false).setShowLine(false) + } + + return FormBuilder.createFormBuilder() + .addLabeledComponent("Path to rpm executable:", rpmCommandPathBox) + .addComponentFillVertically(detectedMacrosPanel, 12) + .panel + } + + override fun isModified(): Boolean { + return rpmCommandPath != RpmSpecSettingsState.instance.rpmCommandPath + } + + override fun apply() { + RpmSpecSettingsState.instance.rpmCommandPath = rpmCommandPath + } + + override fun reset() { + rpmCommandPath = RpmSpecSettingsState.instance.rpmCommandPath + detectedPathsList.setListData(RpmMacroUtil.macroPathFiles.mapNotNull { it.canonicalPath }.toTypedArray()) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/carbonblack/intellij/rpmspec/RpmSpecSettingsState.kt b/src/main/kotlin/com/carbonblack/intellij/rpmspec/RpmSpecSettingsState.kt new file mode 100644 index 0000000..3c990e6 --- /dev/null +++ b/src/main/kotlin/com/carbonblack/intellij/rpmspec/RpmSpecSettingsState.kt @@ -0,0 +1,40 @@ +package com.carbonblack.intellij.rpmspec + +import com.carbonblack.intellij.rpmmacro.RpmMacroUtil +import com.intellij.openapi.components.* +import com.intellij.openapi.diagnostic.Logger +import com.intellij.util.io.exists +import com.intellij.util.xmlb.XmlSerializerUtil +import java.io.File +import java.nio.file.Paths + +private val log = Logger.getInstance(RpmMacroUtil::class.java) + +@State(name = "RpmSpecSettings", storages = [Storage("rpmSpec.xml")]) +class RpmSpecSettingsState : PersistentStateComponent { + var rpmCommandPath = findRpmPath() ?: "rpm" + + override fun getState(): RpmSpecSettingsState = this + override fun loadState(state: RpmSpecSettingsState) { + XmlSerializerUtil.copyBean(state, this) + } + + companion object { + val instance: RpmSpecSettingsState + get() = ServiceManager.getService(RpmSpecSettingsState::class.java) + + private fun findRpmPath(): String? { + return try { + System.getenv().getOrDefault("PATH", "") + .split(File.pathSeparator) + .map { Paths.get(it).resolve("rpm") } + .find { it.exists() } + ?.toAbsolutePath() + ?.toString() + } catch (e: Exception) { + log.warn("Error trying to find rpm executable.", e) + null + } + } + } +} \ No newline at end of file diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 5b21740..6632d85 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -37,6 +37,10 @@ + + diff --git a/src/test/kotlin/com/carbonblack/intellij/rpmmacro/RpmMacroUtilTest.kt b/src/test/kotlin/com/carbonblack/intellij/rpmmacro/RpmMacroUtilTest.kt index ae062b5..d856aa5 100644 --- a/src/test/kotlin/com/carbonblack/intellij/rpmmacro/RpmMacroUtilTest.kt +++ b/src/test/kotlin/com/carbonblack/intellij/rpmmacro/RpmMacroUtilTest.kt @@ -1,5 +1,6 @@ package com.carbonblack.intellij.rpmmacro +import com.carbonblack.intellij.rpmspec.RpmSpecSettingsState import com.intellij.testFramework.fixtures.BasePlatformTestCase import io.mockk.clearAllMocks import io.mockk.every @@ -70,7 +71,9 @@ class RpmMacroUtilTest : BasePlatformTestCase() { clearAllMocks() mockkConstructor(ProcessBuilder::class) - every { anyConstructed().command(listOf("rpm", "--showrc")) } answers { + every { + anyConstructed().command(listOf(RpmSpecSettingsState.instance.rpmCommandPath, "--showrc")) + } answers { (callOriginal()).command("unknown-command") }