set up new mechanism for unlisted subcommands

For the build automation, there will be lots of subcommands that are meant
to run in scripted environments.  They are not intended for interactive use.
Although they sometimes might be useful interactively, they might also
sometimes be dangerous to run interactively because they rely on the
presense of a VM/container, modify the local environment, or even run
things as root.
This commit is contained in:
Michael Pöhn 2025-10-01 15:03:41 +02:00 committed by Hans-Christoph Steiner
parent 3e5a8e625d
commit 6cbef943ac
2 changed files with 40 additions and 2 deletions

View file

@ -55,6 +55,18 @@ COMMANDS = OrderedDict([
("mirror", _("Download complete mirrors of small repos")), ("mirror", _("Download complete mirrors of small repos")),
]) ])
# The list of subcommands that are not advertised as public api,
# intended for the use-case of breaking down builds into atomic steps.
#
# For the build automation, there will be lots of subcommands that are
# meant to run in scripted environments. They are not intended for
# interactive use. Although they sometimes might be useful
# interactively, they might also sometimes be dangerous to run
# interactively because they rely on the presense of a VM/container,
# modify the local environment, or even run things as root.
COMMANDS_INTERNAL = [
]
def print_help(available_plugins=None): def print_help(available_plugins=None):
print(_("usage: ") + _("fdroid [<command>] [-h|--help|--version|<args>]")) print(_("usage: ") + _("fdroid [<command>] [-h|--help|--version|<args>]"))
@ -136,7 +148,12 @@ def main():
sys.exit(0) sys.exit(0)
command = sys.argv[1] command = sys.argv[1]
if command not in COMMANDS and command not in available_plugins: command_not_found = (
command not in COMMANDS
and command not in COMMANDS_INTERNAL
and command not in available_plugins
)
if command_not_found:
if command in ('-h', '--help'): if command in ('-h', '--help'):
print_help(available_plugins=available_plugins) print_help(available_plugins=available_plugins)
sys.exit(0) sys.exit(0)
@ -186,7 +203,7 @@ def main():
sys.argv[0] += ' ' + command sys.argv[0] += ' ' + command
del sys.argv[1] del sys.argv[1]
if command in COMMANDS.keys(): if command in COMMANDS.keys() or command in COMMANDS_INTERNAL:
# import is named import_subcommand internally b/c import is reserved by Python # import is named import_subcommand internally b/c import is reserved by Python
command = 'import_subcommand' if command == 'import' else command command = 'import_subcommand' if command == 'import' else command
mod = __import__('fdroidserver.' + command, None, None, [command]) mod = __import__('fdroidserver.' + command, None, None, [command])

View file

@ -1046,6 +1046,27 @@ def get_local_metadata_files():
return glob.glob('.fdroid.[a-jl-z]*[a-rt-z]') return glob.glob('.fdroid.[a-jl-z]*[a-rt-z]')
def split_pkg_arg(appid_versionCode_pair):
"""Split 'appid:versionCode' pair into 2 separate values safely.
:raises ValueError: if argument is not parseable
:return: (appid, versionCode) tuple with the 2 parsed values
"""
tokens = appid_versionCode_pair.split(":")
if len(tokens) != 2:
raise ValueError(
_("'{}' is not a valid pair of the form appId:versionCode pair").format(
appid_versionCode_pair
)
)
if not is_valid_package_name(tokens[0]):
raise ValueError(
_("'{}' does not start with a valid appId").format(appid_versionCode_pair)
)
versionCode = version_code_string_to_int(tokens[1])
return tokens[0], versionCode
def read_pkg_args(appid_versionCode_pairs, allow_version_codes=False): def read_pkg_args(appid_versionCode_pairs, allow_version_codes=False):
"""No summary. """No summary.