diff --git a/fdroidserver/__main__.py b/fdroidserver/__main__.py index 83a0c81c..5a2241f3 100755 --- a/fdroidserver/__main__.py +++ b/fdroidserver/__main__.py @@ -55,6 +55,18 @@ COMMANDS = OrderedDict([ ("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): print(_("usage: ") + _("fdroid [] [-h|--help|--version|]")) @@ -136,7 +148,12 @@ def main(): sys.exit(0) 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'): print_help(available_plugins=available_plugins) sys.exit(0) @@ -186,7 +203,7 @@ def main(): sys.argv[0] += ' ' + command 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 command = 'import_subcommand' if command == 'import' else command mod = __import__('fdroidserver.' + command, None, None, [command]) diff --git a/fdroidserver/common.py b/fdroidserver/common.py index e3062129..247ee733 100644 --- a/fdroidserver/common.py +++ b/fdroidserver/common.py @@ -1046,6 +1046,27 @@ def get_local_metadata_files(): 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): """No summary.