Skip to content

Commit 4eedf22

Browse files
committedFeb 13, 2025·
feat(cli): Add a command to list installed plugins
Add a command to list all installed plugins and their configuration options. The command is limited to plugins using the new plugin API, so package manager plugins are not yet shown. Once these are also migrated, the `--plugins` option of the `requirements` command will be removed. Signed-off-by: Martin Nonnenmacher <martin.nonnenmacher@bosch.com>
1 parent 545475b commit 4eedf22

File tree

5 files changed

+315
-3
lines changed

5 files changed

+315
-3
lines changed
 

‎integrations/completions/ort-completion.bash

+60-1
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ _ort() {
115115
_ort_notify $(( i + 1 ))
116116
return
117117
;;
118+
plugins)
119+
_ort_plugins $(( i + 1 ))
120+
return
121+
;;
118122
report)
119123
_ort_report $(( i + 1 ))
120124
return
@@ -176,7 +180,7 @@ _ort() {
176180
"--help")
177181
;;
178182
*)
179-
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}"))
183+
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}"))
180184
;;
181185
esac
182186
}
@@ -1054,6 +1058,61 @@ _ort_notify() {
10541058
esac
10551059
}
10561060
1061+
_ort_plugins() {
1062+
local i=$1
1063+
local in_param=''
1064+
local fixed_arg_names=()
1065+
local vararg_name=''
1066+
local can_parse_options=1
1067+
1068+
while [[ ${i} -lt $COMP_CWORD ]]; do
1069+
if [[ ${can_parse_options} -eq 1 ]]; then
1070+
case "${COMP_WORDS[$i]}" in
1071+
--)
1072+
can_parse_options=0
1073+
(( i = i + 1 ));
1074+
continue
1075+
;;
1076+
--types)
1077+
__skip_opt_eq
1078+
(( i = i + 1 ))
1079+
[[ ${i} -gt COMP_CWORD ]] && in_param='--types' || in_param=''
1080+
continue
1081+
;;
1082+
-h|--help)
1083+
__skip_opt_eq
1084+
in_param=''
1085+
continue
1086+
;;
1087+
esac
1088+
fi
1089+
case "${COMP_WORDS[$i]}" in
1090+
*)
1091+
(( i = i + 1 ))
1092+
# drop the head of the array
1093+
fixed_arg_names=("${fixed_arg_names[@]:1}")
1094+
;;
1095+
esac
1096+
done
1097+
local word="${COMP_WORDS[$COMP_CWORD]}"
1098+
if [[ "${word}" =~ ^[-] ]]; then
1099+
COMPREPLY=($(compgen -W '--types -h --help' -- "${word}"))
1100+
return
1101+
fi
1102+
1103+
# We're either at an option's value, or the first remaining fixed size
1104+
# arg, or the vararg if there are no fixed args left
1105+
[[ -z "${in_param}" ]] && in_param=${fixed_arg_names[0]}
1106+
[[ -z "${in_param}" ]] && in_param=${vararg_name}
1107+
1108+
case "${in_param}" in
1109+
"--types")
1110+
;;
1111+
"--help")
1112+
;;
1113+
esac
1114+
}
1115+
10571116
_ort_report() {
10581117
local i=$1
10591118
local in_param=''

‎integrations/completions/ort-completion.fish

+9-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44

55
### Setup for ort
6-
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'
6+
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'
77

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

137137

138+
### Setup for plugins
139+
complete -c ort -f -n __fish_use_subcommand -a plugins -d 'Print information about the installed ORT plugins.'
140+
141+
## Options for plugins
142+
complete -c ort -n "__fish_seen_subcommand_from plugins" -l types -r -d 'A comma-separated list of plugin types to show.'
143+
complete -c ort -n "__fish_seen_subcommand_from plugins" -s h -l help -d 'Show this message and exit'
144+
145+
138146
### Setup for report
139147
complete -c ort -f -n __fish_use_subcommand -a report -d 'Present Analyzer, Scanner and Evaluator results in various formats.'
140148

‎integrations/completions/ort-completion.zsh

+60-1
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ _ort() {
120120
_ort_notify $(( i + 1 ))
121121
return
122122
;;
123+
plugins)
124+
_ort_plugins $(( i + 1 ))
125+
return
126+
;;
123127
report)
124128
_ort_report $(( i + 1 ))
125129
return
@@ -181,7 +185,7 @@ _ort() {
181185
"--help")
182186
;;
183187
*)
184-
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}"))
188+
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}"))
185189
;;
186190
esac
187191
}
@@ -1059,6 +1063,61 @@ _ort_notify() {
10591063
esac
10601064
}
10611065
1066+
_ort_plugins() {
1067+
local i=$1
1068+
local in_param=''
1069+
local fixed_arg_names=()
1070+
local vararg_name=''
1071+
local can_parse_options=1
1072+
1073+
while [[ ${i} -lt $COMP_CWORD ]]; do
1074+
if [[ ${can_parse_options} -eq 1 ]]; then
1075+
case "${COMP_WORDS[$i]}" in
1076+
--)
1077+
can_parse_options=0
1078+
(( i = i + 1 ));
1079+
continue
1080+
;;
1081+
--types)
1082+
__skip_opt_eq
1083+
(( i = i + 1 ))
1084+
[[ ${i} -gt COMP_CWORD ]] && in_param='--types' || in_param=''
1085+
continue
1086+
;;
1087+
-h|--help)
1088+
__skip_opt_eq
1089+
in_param=''
1090+
continue
1091+
;;
1092+
esac
1093+
fi
1094+
case "${COMP_WORDS[$i]}" in
1095+
*)
1096+
(( i = i + 1 ))
1097+
# drop the head of the array
1098+
fixed_arg_names=("${fixed_arg_names[@]:1}")
1099+
;;
1100+
esac
1101+
done
1102+
local word="${COMP_WORDS[$COMP_CWORD]}"
1103+
if [[ "${word}" =~ ^[-] ]]; then
1104+
COMPREPLY=($(compgen -W '--types -h --help' -- "${word}"))
1105+
return
1106+
fi
1107+
1108+
# We're either at an option's value, or the first remaining fixed size
1109+
# arg, or the vararg if there are no fixed args left
1110+
[[ -z "${in_param}" ]] && in_param=${fixed_arg_names[0]}
1111+
[[ -z "${in_param}" ]] && in_param=${vararg_name}
1112+
1113+
case "${in_param}" in
1114+
"--types")
1115+
;;
1116+
"--help")
1117+
;;
1118+
esac
1119+
}
1120+
10621121
_ort_report() {
10631122
local i=$1
10641123
local in_param=''
+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright (C) 2025 The ORT Project Authors (see <https://github.com/oss-review-toolkit/ort/blob/main/NOTICE>)
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
* License-Filename: LICENSE
18+
*/
19+
20+
plugins {
21+
// Apply precompiled plugins.
22+
id("ort-plugin-conventions")
23+
}
24+
25+
dependencies {
26+
api(projects.plugins.commands.commandApi)
27+
28+
ksp(projects.plugins.commands.commandApi)
29+
30+
implementation(projects.advisor)
31+
implementation(projects.downloader)
32+
implementation(projects.plugins.api)
33+
implementation(projects.plugins.packageConfigurationProviders.packageConfigurationProviderApi)
34+
implementation(projects.plugins.packageCurationProviders.packageCurationProviderApi)
35+
implementation(projects.reporter)
36+
implementation(projects.scanner)
37+
38+
implementation(libs.clikt)
39+
implementation(libs.mordant)
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
/*
2+
* Copyright (C) 2025 The ORT Project Authors (see <https://github.com/oss-review-toolkit/ort/blob/main/NOTICE>)
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* SPDX-License-Identifier: Apache-2.0
17+
* License-Filename: LICENSE
18+
*/
19+
20+
package org.ossreviewtoolkit.plugins.commands.plugins
21+
22+
import com.github.ajalt.clikt.parameters.options.default
23+
import com.github.ajalt.clikt.parameters.options.option
24+
import com.github.ajalt.clikt.parameters.options.split
25+
import com.github.ajalt.mordant.widgets.HorizontalRule
26+
import com.github.ajalt.mordant.widgets.UnorderedList
27+
28+
import org.ossreviewtoolkit.advisor.AdviceProviderFactory
29+
import org.ossreviewtoolkit.downloader.VersionControlSystemFactory
30+
import org.ossreviewtoolkit.plugins.api.OrtPlugin
31+
import org.ossreviewtoolkit.plugins.api.PluginDescriptor
32+
import org.ossreviewtoolkit.plugins.commands.api.OrtCommand
33+
import org.ossreviewtoolkit.plugins.commands.api.OrtCommandFactory
34+
import org.ossreviewtoolkit.plugins.packageconfigurationproviders.api.PackageConfigurationProviderFactory
35+
import org.ossreviewtoolkit.plugins.packagecurationproviders.api.PackageCurationProviderFactory
36+
import org.ossreviewtoolkit.reporter.ReporterFactory
37+
import org.ossreviewtoolkit.scanner.ScannerWrapperFactory
38+
39+
@OrtPlugin(
40+
id = "plugins",
41+
displayName = "plugins command",
42+
description = "Print information about the installed ORT plugins.",
43+
factory = OrtCommandFactory::class
44+
)
45+
class PluginsCommand(descriptor: PluginDescriptor = PluginsCommandFactory.descriptor) : OrtCommand(descriptor) {
46+
private val types by option(
47+
"--types",
48+
help = "A comma-separated list of plugin types to show."
49+
).split(",").default(PluginType.entries.map { it.optionName })
50+
51+
override fun run() {
52+
types.forEach { type ->
53+
PluginType.entries.find { it.optionName == type }?.let { pluginType ->
54+
renderPlugins(pluginType.title, pluginType.descriptors.value)
55+
}
56+
}
57+
}
58+
59+
private fun renderPlugins(title: String, plugins: List<PluginDescriptor>) {
60+
echo(HorizontalRule(title, "="))
61+
echo()
62+
63+
plugins.forEach { plugin ->
64+
echo(
65+
HorizontalRule(
66+
buildString {
67+
append(plugin.displayName)
68+
if (plugin.id != plugin.displayName) append(" (id: ${plugin.id})")
69+
},
70+
"-"
71+
)
72+
)
73+
echo()
74+
echo(plugin.description)
75+
echo()
76+
77+
if (plugin.options.isNotEmpty()) {
78+
echo("Configuration options:")
79+
80+
echo(
81+
UnorderedList(
82+
listEntries = plugin.options.map { option ->
83+
buildString {
84+
append("${option.name}: ${option.type.name}")
85+
option.defaultValue?.also { append(" (Default: $it)") }
86+
if (option.isRequired) append(" (Required)")
87+
appendLine()
88+
append(option.description)
89+
}
90+
}.toTypedArray(),
91+
bulletText = "*"
92+
)
93+
)
94+
95+
echo()
96+
}
97+
}
98+
}
99+
}
100+
101+
private enum class PluginType(
102+
val optionName: String,
103+
val title: String,
104+
val descriptors: Lazy<List<PluginDescriptor>>
105+
) {
106+
ADVICE_PROVIDERS(
107+
"advice-providers",
108+
"Advice Providers",
109+
lazy { AdviceProviderFactory.ALL.map { it.value.descriptor } }
110+
),
111+
COMMANDS(
112+
"commands",
113+
"CLI Commands",
114+
lazy { OrtCommandFactory.ALL.map { it.value.descriptor } }
115+
),
116+
PACKAGE_CONFIGURATION_PROVIDERS(
117+
"package-configuration-providers",
118+
"Package Configuration Providers",
119+
lazy { PackageConfigurationProviderFactory.ALL.map { it.value.descriptor } }
120+
),
121+
PACKAGE_CURATION_PROVIDERS(
122+
"package-curation-providers",
123+
"Package Curation Providers",
124+
lazy { PackageCurationProviderFactory.ALL.map { it.value.descriptor } }
125+
),
126+
PACKAGE_MANAGERS(
127+
"package-managers",
128+
"Package Managers (TO BE IMPLEMENTED)",
129+
lazy { emptyList() }
130+
),
131+
REPORTERS(
132+
"reporters",
133+
"Reporters",
134+
lazy { ReporterFactory.ALL.map { it.value.descriptor } }
135+
),
136+
SCANNERS(
137+
"scanners",
138+
"Scanners",
139+
lazy { ScannerWrapperFactory.ALL.map { it.value.descriptor } }
140+
),
141+
VERSION_CONTROL_SYSTEMS(
142+
"version-control-systems",
143+
"Version Control Systems",
144+
lazy { VersionControlSystemFactory.ALL.map { it.value.descriptor } }
145+
)
146+
}

0 commit comments

Comments
 (0)
Please sign in to comment.