Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cli): Add a command to list installed plugins #9140

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 60 additions & 1 deletion integrations/completions/ort-completion.bash
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ _ort() {
_ort_notify $(( i + 1 ))
return
;;
plugins)
_ort_plugins $(( i + 1 ))
return
;;
report)
_ort_report $(( i + 1 ))
return
Expand Down Expand Up @@ -165,7 +169,7 @@ _ort() {
--help)
;;
*)
COMPREPLY=($(compgen -W 'advise analyze compare config download evaluate migrate notify report requirements scan upload-curations upload-result-to-postgres upload-result-to-sw360' -- "${word}"))
COMPREPLY=($(compgen -W 'advise analyze compare config download evaluate migrate notify plugins report requirements scan upload-curations upload-result-to-postgres upload-result-to-sw360' -- "${word}"))
;;
esac
}
Expand Down Expand Up @@ -1043,6 +1047,61 @@ _ort_notify() {
esac
}

_ort_plugins() {
local i=$1
local in_param=''
local fixed_arg_names=()
local vararg_name=''
local can_parse_options=1

while [[ ${i} -lt $COMP_CWORD ]]; do
if [[ ${can_parse_options} -eq 1 ]]; then
case "${COMP_WORDS[$i]}" in
--)
can_parse_options=0
(( i = i + 1 ));
continue
;;
--types)
__skip_opt_eq
(( i = i + 1 ))
[[ ${i} -gt COMP_CWORD ]] && in_param='--types' || in_param=''
continue
;;
-h|--help)
__skip_opt_eq
in_param=''
continue
;;
esac
fi
case "${COMP_WORDS[$i]}" in
*)
(( i = i + 1 ))
# drop the head of the array
fixed_arg_names=("${fixed_arg_names[@]:1}")
;;
esac
done
local word="${COMP_WORDS[$COMP_CWORD]}"
if [[ "${word}" =~ ^[-] ]]; then
COMPREPLY=($(compgen -W '--types -h --help' -- "${word}"))
return
fi

# We're either at an option's value, or the first remaining fixed size
# arg, or the vararg if there are no fixed args left
[[ -z "${in_param}" ]] && in_param=${fixed_arg_names[0]}
[[ -z "${in_param}" ]] && in_param=${vararg_name}

case "${in_param}" in
--types)
;;
--help)
;;
esac
}

_ort_report() {
local i=$1
local in_param=''
Expand Down
10 changes: 9 additions & 1 deletion integrations/completions/ort-completion.fish
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@


### Setup for ort
set -l ort_subcommands 'advise analyze compare config download evaluate migrate notify report requirements scan upload-curations upload-result-to-postgres upload-result-to-sw360'
set -l ort_subcommands 'advise analyze compare config download evaluate migrate notify plugins report requirements scan upload-curations upload-result-to-postgres upload-result-to-sw360'

## Options for ort
complete -c ort -n "not __fish_seen_subcommand_from $ort_subcommands" -l config -s c -r -F -d 'The path to a configuration file.'
Expand Down Expand Up @@ -135,6 +135,14 @@ complete -c ort -n "__fish_seen_subcommand_from notify" -l label -s l -r -d 'Set
complete -c ort -n "__fish_seen_subcommand_from notify" -s h -l help -d 'Show this message and exit'


### Setup for plugins
complete -c ort -f -n __fish_use_subcommand -a plugins -d 'Print information about the installed ORT plugins.'

## Options for plugins
complete -c ort -n "__fish_seen_subcommand_from plugins" -l types -r -d 'A comma-separated list plugin types to show.'
complete -c ort -n "__fish_seen_subcommand_from plugins" -s h -l help -d 'Show this message and exit'


### Setup for report
complete -c ort -f -n __fish_use_subcommand -a report -d 'Present Analyzer, Scanner and Evaluator results in various formats.'

Expand Down
61 changes: 60 additions & 1 deletion integrations/completions/ort-completion.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ _ort() {
_ort_notify $(( i + 1 ))
return
;;
plugins)
_ort_plugins $(( i + 1 ))
return
;;
report)
_ort_report $(( i + 1 ))
return
Expand Down Expand Up @@ -170,7 +174,7 @@ _ort() {
--help)
;;
*)
COMPREPLY=($(compgen -W 'advise analyze compare config download evaluate migrate notify report requirements scan upload-curations upload-result-to-postgres upload-result-to-sw360' -- "${word}"))
COMPREPLY=($(compgen -W 'advise analyze compare config download evaluate migrate notify plugins report requirements scan upload-curations upload-result-to-postgres upload-result-to-sw360' -- "${word}"))
;;
esac
}
Expand Down Expand Up @@ -1048,6 +1052,61 @@ _ort_notify() {
esac
}

_ort_plugins() {
local i=$1
local in_param=''
local fixed_arg_names=()
local vararg_name=''
local can_parse_options=1

while [[ ${i} -lt $COMP_CWORD ]]; do
if [[ ${can_parse_options} -eq 1 ]]; then
case "${COMP_WORDS[$i]}" in
--)
can_parse_options=0
(( i = i + 1 ));
continue
;;
--types)
__skip_opt_eq
(( i = i + 1 ))
[[ ${i} -gt COMP_CWORD ]] && in_param='--types' || in_param=''
continue
;;
-h|--help)
__skip_opt_eq
in_param=''
continue
;;
esac
fi
case "${COMP_WORDS[$i]}" in
*)
(( i = i + 1 ))
# drop the head of the array
fixed_arg_names=("${fixed_arg_names[@]:1}")
;;
esac
done
local word="${COMP_WORDS[$COMP_CWORD]}"
if [[ "${word}" =~ ^[-] ]]; then
COMPREPLY=($(compgen -W '--types -h --help' -- "${word}"))
return
fi

# We're either at an option's value, or the first remaining fixed size
# arg, or the vararg if there are no fixed args left
[[ -z "${in_param}" ]] && in_param=${fixed_arg_names[0]}
[[ -z "${in_param}" ]] && in_param=${vararg_name}

case "${in_param}" in
--types)
;;
--help)
;;
esac
}

_ort_report() {
local i=$1
local in_param=''
Expand Down
35 changes: 35 additions & 0 deletions plugins/commands/plugins/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (C) 2023 The ORT Project Authors (see <https://github.com/oss-review-toolkit/ort/blob/main/NOTICE>)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be 2024.

*
* 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
*
* https://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.
*
* SPDX-License-Identifier: Apache-2.0
* License-Filename: LICENSE
*/

plugins {
// Apply precompiled plugins.
id("ort-library-conventions")
}

dependencies {
api(projects.plugins.commands.commandApi)

implementation(projects.advisor)
implementation(projects.plugins.api)
implementation(projects.plugins.packageConfigurationProviders.packageConfigurationProviderApi)
implementation(projects.plugins.packageCurationProviders.packageCurationProviderApi)

implementation(libs.clikt)
implementation(libs.mordant)
}
112 changes: 112 additions & 0 deletions plugins/commands/plugins/src/main/kotlin/PluginsCommand.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* Copyright (C) 2024 The ORT Project Authors (see <https://github.com/oss-review-toolkit/ort/blob/main/NOTICE>)
*
* 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
*
* https://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.
*
* SPDX-License-Identifier: Apache-2.0
* License-Filename: LICENSE
*/

package org.ossreviewtoolkit.plugins.commands.plugins

import com.github.ajalt.clikt.parameters.options.default
import com.github.ajalt.clikt.parameters.options.option
import com.github.ajalt.clikt.parameters.options.split
import com.github.ajalt.mordant.widgets.HorizontalRule
import com.github.ajalt.mordant.widgets.UnorderedList

import org.ossreviewtoolkit.advisor.AdviceProviderFactory
import org.ossreviewtoolkit.plugins.api.PluginDescriptor
import org.ossreviewtoolkit.plugins.commands.api.OrtCommand
import org.ossreviewtoolkit.plugins.packageconfigurationproviders.api.PackageConfigurationProviderFactory
import org.ossreviewtoolkit.plugins.packagecurationproviders.api.PackageCurationProviderFactory

class PluginsCommand : OrtCommand(
name = "plugins",
help = "Print information about the installed ORT plugins."
) {
private val types by option(
"--types",
help = "A comma-separated list of plugin types to show."
).split(",").default(PluginType.entries.map { it.optionName })

override fun run() {
echo(HorizontalRule("Installed ORT Plugins", "="))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I'd omit this rule as it's clear from the command that ORT plugins are listed, and instead "promote" plugin type rules from "-" to "=", and introduce "-" rules for the individual plugins to better separate their options from the next plugin.

echo()

types.forEach { type ->
PluginType.entries.find { it.optionName == type }?.let { pluginType ->
renderPlugins(pluginType.title, pluginType.descriptors.value)
}
}
}

private fun renderPlugins(title: String, plugins: List<PluginDescriptor>) {
echo(HorizontalRule(title, "-"))
echo()

plugins.forEach { plugin ->
echo(
buildString {
append(plugin.displayName)
if (plugin.id != plugin.displayName) append(" (id: ${plugin.id})")
}
)
echo(plugin.description)
echo()

if (plugin.options.isNotEmpty()) {
echo("Configuration options:")

echo(
UnorderedList(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about using a table instead, with columns for the option name, type, and description?

listEntries = plugin.options.map { option ->
buildString {
append("${option.name}: ${option.type.name}")
option.defaultValue?.let { append(" (Default: $it)") }
if (option.isRequired) append(" (Required)")
appendLine()
append(option.description)
}
}.toTypedArray(),
bulletText = "*"
)
)

echo()
}
}
}
}

private enum class PluginType(
val optionName: String,
val title: String,
val descriptors: Lazy<List<PluginDescriptor>>
) {
ADVICE_PROVIDERS(
"advice-providers",
"Advice Providers",
lazy { AdviceProviderFactory.ALL.map { it.value.descriptor } }
),
PACKAGE_CONFIGURATION_PROVIDERS(
"package-configuration-providers",
"Package Configuration Providers",
lazy { PackageConfigurationProviderFactory.ALL.map { it.value.descriptor } }
),
PACKAGE_CURATION_PROVIDERS(
"package-curation-providers",
"Package Curation Providers",
lazy { PackageCurationProviderFactory.ALL.map { it.value.descriptor } }
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
org.ossreviewtoolkit.plugins.commands.plugins.PluginsCommand
Loading