[elbe-devel] [PATCH v2 4/5] elbepack: control: migrate to argparse
Thomas Weißschuh
thomas.weissschuh at linutronix.de
Mon Jul 15 17:31:29 CEST 2024
argparse has various advantages of optparse:
* Autogenerated command synopsis.
* Required arguments.
* Flexible argument types.
* Subparsers.
Furthermore optparse is deprecated since Python 3.2 (2011).
Replace the custom action registry with a simple dispatch table, which
is both less code and easier to understand.
Also move the options to the subcommands where they make sense.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh at linutronix.de>
---
elbepack/commands/control.py | 136 ++-----
elbepack/soapclient.py | 856 ++++++++++++++++---------------------------
2 files changed, 348 insertions(+), 644 deletions(-)
diff --git a/elbepack/commands/control.py b/elbepack/commands/control.py
index feed0c71b3cd..6f737b229196 100644
--- a/elbepack/commands/control.py
+++ b/elbepack/commands/control.py
@@ -2,125 +2,76 @@
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: 2014-2017 Linutronix GmbH
+import argparse
import socket
import sys
from http.client import BadStatusLine
-from optparse import OptionGroup, OptionParser
from urllib.error import URLError
from suds import WebFault
+from elbepack.cli import add_arguments_from_decorated_function
from elbepack.config import cfg
from elbepack.elbexml import ValidationMode
-from elbepack.soapclient import ClientAction, ElbeSoapClient
+from elbepack.soapclient import ElbeSoapClient, client_actions
def run_command(argv):
- oparser = OptionParser(usage='usage: elbe control [options] <command>')
+ aparser = argparse.ArgumentParser(prog='elbe control')
- oparser.add_option('--host', dest='host', default=cfg['soaphost'],
- help='Ip or hostname of elbe-daemon.')
+ aparser.add_argument('--host', dest='host', default=cfg['soaphost'],
+ help='Ip or hostname of elbe-daemon.')
- oparser.add_option('--port', dest='port', default=cfg['soapport'],
- help='Port of soap itf on elbe-daemon.')
+ aparser.add_argument('--port', dest='port', default=cfg['soapport'],
+ help='Port of soap itf on elbe-daemon.')
- oparser.add_option('--pass', dest='passwd', default=cfg['elbepass'],
- help='Password (default is foo).')
+ aparser.add_argument('--pass', dest='passwd', default=cfg['elbepass'],
+ help='Password (default is foo).')
- oparser.add_option('--user', dest='user', default=cfg['elbeuser'],
- help='Username (default is root).')
+ aparser.add_argument('--user', dest='user', default=cfg['elbeuser'],
+ help='Username (default is root).')
- oparser.add_option(
+ aparser.add_argument(
'--retries',
dest='retries',
- default='10',
+ type=int,
+ default=10,
help='How many times to retry the connection to the server before '
'giving up (default is 10 times, yielding 10 seconds).')
- oparser.add_option(
- '--build-bin',
- action='store_true',
- dest='build_bin',
- default=False,
- help='Build binary repository CDROM, for exact reproduction.')
-
- oparser.add_option('--build-sources', action='store_true',
- dest='build_sources', default=False,
- help='Build source CDROM')
-
- oparser.add_option(
- '--skip-pbuilder',
- action='store_true',
- dest='skip_pbuilder',
- default=False,
- help="skip pbuilder section of XML (don't build packages)")
-
- oparser.add_option('--output',
- dest='output', default=None,
- help='Output files to <directory>')
-
- oparser.add_option('--matches', dest='matches', default=False,
- help='Select files based on wildcard expression.')
-
- oparser.add_option('--pbuilder-only', action='store_true',
- dest='pbuilder_only', default=False,
- help='Only list/download pbuilder Files')
-
- oparser.add_option('--cpuset', default=-1, type='int',
- help='Limit cpuset of pbuilder commands (bitmask)'
- '(defaults to -1 for all CPUs)')
-
- oparser.add_option('--profile', dest='profile', default='',
- help='Make pbuilder commands build the specified profile')
-
- oparser.add_option('--cross', dest='cross', default=False,
- action='store_true',
- help='Creates an environment for crossbuilding if '
- 'combined with create. Combined with build it'
- ' will use this environment.')
-
- oparser.add_option('--no-ccache', dest='noccache', default=False,
- action='store_true',
- help="Deactivates the compiler cache 'ccache'")
-
- oparser.add_option('--ccache-size', dest='ccachesize', default='10G',
- action='store', type='string',
- help='set a limit for the compiler cache size '
- '(should be a number followed by an optional '
- 'suffix: k, M, G, T. Use 0 for no limit.)')
-
- devel = OptionGroup(
- oparser,
+ devel = aparser.add_argument_group(
'options for elbe developers',
"Caution: Don't use these options in a productive environment")
- devel.add_option('--skip-urlcheck', action='store_true',
- dest='url_validation', default=ValidationMode.CHECK_ALL,
- help='Skip URL Check inside initvm')
+ devel.add_argument('--skip-urlcheck', action='store_true',
+ dest='url_validation', default=ValidationMode.CHECK_ALL,
+ help='Skip URL Check inside initvm')
- devel.add_option('--debug', action='store_true',
- dest='debug', default=False,
- help='Enable debug mode.')
+ devel.add_argument('--debug', action='store_true',
+ dest='debug', default=False,
+ help='Enable debug mode.')
- (opt, args) = oparser.parse_args(argv)
+ subparsers = aparser.add_subparsers(required=True)
- if not args:
- print('elbe control - no subcommand given', file=sys.stderr)
- ClientAction.print_actions()
- return
+ for action_name, do_action in client_actions.items():
+ action_parser = subparsers.add_parser(action_name)
+ action_parser.set_defaults(func=do_action)
+ add_arguments_from_decorated_function(action_parser, do_action)
+
+ args = aparser.parse_args(argv)
+ args.parser = aparser
try:
control = ElbeSoapClient(
- opt.host,
- opt.port,
- opt.user,
- opt.passwd,
- debug=opt.debug,
- retries=int(
- opt.retries))
+ args.host,
+ args.port,
+ args.user,
+ args.passwd,
+ debug=args.debug,
+ retries=args.retries)
except URLError:
print(
- f'Failed to connect to Soap server {opt.host}:{opt.port}\n',
+ f'Failed to connect to Soap server {args.host}:{args.port}\n',
file=sys.stderr)
print('', file=sys.stderr)
print('Check, whether the initvm is actually running.', file=sys.stderr)
@@ -128,7 +79,7 @@ def run_command(argv):
sys.exit(13)
except socket.error:
print(
- f'Failed to connect to Soap server {opt.host}:{opt.port}\n',
+ f'Failed to connect to Soap server {args.host}:{args.port}\n',
file=sys.stderr)
print('', file=sys.stderr)
print(
@@ -138,7 +89,7 @@ def run_command(argv):
sys.exit(14)
except BadStatusLine:
print(
- f'Failed to connect to Soap server {opt.host}:{opt.port}\n',
+ f'Failed to connect to Soap server {args.host}:{args.port}\n',
file=sys.stderr)
print('', file=sys.stderr)
print('Check, whether the initvm is actually running.', file=sys.stderr)
@@ -146,14 +97,7 @@ def run_command(argv):
sys.exit(15)
try:
- action = ClientAction(args[0])
- except KeyError:
- print('elbe control - unknown subcommand', file=sys.stderr)
- ClientAction.print_actions()
- sys.exit(25)
-
- try:
- action.execute(control, opt, args[1:])
+ args.func(control, args)
except WebFault as e:
print('Server returned error:', file=sys.stderr)
print('', file=sys.stderr)
diff --git a/elbepack/soapclient.py b/elbepack/soapclient.py
index a3bab5865a18..861027a52543 100644
--- a/elbepack/soapclient.py
+++ b/elbepack/soapclient.py
@@ -19,6 +19,7 @@ import debian.deb822
from suds import WebFault
from suds.client import Client
+from elbepack.cli import add_argument
from elbepack.config import cfg
from elbepack.elbexml import ElbeXML, ValidationMode
from elbepack.version import elbe_version
@@ -125,593 +126,352 @@ class ElbeSoapClient:
part = part + 1
-class ClientAction:
- actiondict = {}
+def _add_project_dir_argument(f):
+ return add_argument('project_dir')(f)
- @classmethod
- def register(cls, action):
- cls.actiondict[action.tag] = action
-
- @classmethod
- def print_actions(cls):
- print('available subcommands are:', file=sys.stderr)
- for a in cls.actiondict:
- print(f' {a}', file=sys.stderr)
-
- def __new__(cls, node):
- action = cls.actiondict[node]
- return object.__new__(action)
-
- def __init__(self, node):
- self.node = node
-
- @staticmethod
- def upload_file(append, build_dir, filename):
-
- size = 1024 * 1024
-
- with open(filename, 'rb') as f:
-
- while True:
-
- bin_data = f.read(size)
- data = binascii.b2a_base64(bin_data)
-
- if not isinstance(data, str):
- data = data.decode('ascii')
-
- append(build_dir, data)
-
- if len(bin_data) != size:
- break
-
- def execute(self, _client, _opt, _args):
- raise NotImplementedError('execute() not implemented')
-
-
-class RemoveLogAction(ClientAction):
-
- tag = 'rm_log'
-
- def execute(self, client, _opt, args):
- if len(args) != 1:
- print('usage: elbe control rm_log <project_dir>', file=sys.stderr)
- sys.exit(172)
-
- builddir = args[0]
- client.service.rm_log(builddir)
-
-
-ClientAction.register(RemoveLogAction)
-
-
-class ListProjectsAction(ClientAction):
-
- tag = 'list_projects'
-
- def execute(self, client, _opt, _args):
- projects = client.service.list_projects()
-
- try:
- for p in projects.SoapProject:
- print(
- f'{p.builddir}\t{p.name}\t{p.version}\t{p.status}\t'
- f'{p.edit}')
- except AttributeError:
- print('No projects configured in initvm')
-
-
-ClientAction.register(ListProjectsAction)
-
-
-class ListUsersAction(ClientAction):
-
- tag = 'list_users'
-
- def execute(self, client, _opt, _args):
- users = client.service.list_users()
-
- for u in users.string:
- print(u)
-
-
-ClientAction.register(ListUsersAction)
-
-
-class AddUserAction(ClientAction):
- tag = 'add_user'
-
- def execute(self, client, _opt, args):
- if len(args) != 4:
- print(
- 'usage: elbe control add_user <name> <fullname> <password> <email>',
- file=sys.stderr)
- sys.exit(173)
-
- name = args[0]
- fullname = args[1]
- password = args[2]
- email = args[3]
-
- try:
- client.service.add_user(name, fullname, password, email, False)
- except WebFault as e:
- if not hasattr(e.fault, 'faultstring'):
- raise
-
- if not e.fault.faultstring.endswith('already exists in the database'):
- raise
-
- # when we get here, the user we wanted to create already exists.
- # that is fine, and we dont need to do anything now.
-
-
-ClientAction.register(AddUserAction)
-
-
-class CreateProjectAction(ClientAction):
-
- tag = 'create_project'
-
- def execute(self, client, _opt, _args):
-
- uuid = client.service.new_project()
- print(uuid)
-
-
-ClientAction.register(CreateProjectAction)
-
-
-class ResetProjectAction(ClientAction):
-
- tag = 'reset_project'
-
- def execute(self, client, _opt, args):
- if len(args) != 1:
- print(
- 'usage: elbe control reset_project <project_dir>',
- file=sys.stderr)
- sys.exit(174)
-
- builddir = args[0]
- client.service.reset_project(builddir)
-
-
-ClientAction.register(ResetProjectAction)
-
-
-class DeleteProjectAction(ClientAction):
-
- tag = 'del_project'
-
- def execute(self, client, _opt, args):
- if len(args) != 1:
- print(
- 'usage: elbe control del_project <project_dir>',
- file=sys.stderr)
- sys.exit(175)
-
- builddir = args[0]
- client.service.del_project(builddir)
-
-
-ClientAction.register(DeleteProjectAction)
-
-
-class SetXmlAction(ClientAction):
-
- tag = 'set_xml'
-
- def execute(self, client, _opt, args):
- if len(args) != 2:
- print(
- 'usage: elbe control set_xml <project_dir> <xml>',
- file=sys.stderr)
- sys.exit(176)
-
- builddir = args[0]
- filename = args[1]
-
- try:
- x = ElbeXML(
- filename,
- skip_validate=True,
- url_validation=ValidationMode.NO_CHECK)
- except IOError:
- print(f'{filename} is not a valid elbe xml file')
- sys.exit(177)
-
- if not x.has('target'):
- print("<target> is missing, this file can't be built in an initvm",
- file=sys.stderr)
- sys.exit(178)
-
- size = 1024 * 1024
- part = 0
- with open(filename, 'rb') as fp:
- while True:
-
- xml_base64 = binascii.b2a_base64(fp.read(size))
-
- if not isinstance(xml_base64, str):
- xml_base64 = xml_base64.decode('ascii')
-
- # finish upload
- if len(xml_base64) == 1:
- part = client.service.upload_file(builddir,
- 'source.xml',
- xml_base64,
- -1)
- else:
- part = client.service.upload_file(builddir,
- 'source.xml',
- xml_base64,
- part)
- if part == -1:
- print('project busy, upload not allowed')
- return part
- if part == -2:
- print('upload of xml finished')
- return 0
-
-
-ClientAction.register(SetXmlAction)
-
-
-class BuildAction(ClientAction):
-
- tag = 'build'
-
- def execute(self, client, opt, args):
- if len(args) != 1:
- print('usage: elbe control build <project_dir>', file=sys.stderr)
- sys.exit(179)
-
- builddir = args[0]
- client.service.build(builddir, opt.build_bin, opt.build_sources,
- opt.skip_pbuilder)
-
-
-ClientAction.register(BuildAction)
-
-
-class BuildSysrootAction(ClientAction):
-
- tag = 'build_sysroot'
-
- def execute(self, client, _opt, args):
- if len(args) != 1:
- print(
- 'usage: elbe control build-sysroot <project_dir>',
- file=sys.stderr)
- sys.exit(180)
-
- builddir = args[0]
- client.service.build_sysroot(builddir)
-
-
-ClientAction.register(BuildSysrootAction)
+def _client_action_upload_file(append, build_dir, filename):
+ size = 1024 * 1024
-class BuildSDKAction(ClientAction):
+ with open(filename, 'rb') as f:
- tag = 'build_sdk'
-
- def execute(self, client, _opt, args):
- if len(args) != 1:
- print(
- 'usage: elbe control build-sdk <project_dir>',
- file=sys.stderr)
- sys.exit(181)
-
- builddir = args[0]
- client.service.build_sdk(builddir)
-
-
-ClientAction.register(BuildSDKAction)
-
-
-class BuildCDROMsAction(ClientAction):
-
- tag = 'build_cdroms'
-
- def execute(self, client, opt, args):
- if len(args) != 1:
- print(
- 'usage: elbe control build-cdroms [--build-bin|--build-sources] <project_dir>',
- file=sys.stderr)
- sys.exit(182)
-
- if (not opt.build_bin) and (not opt.build_sources):
- print(
- 'usage: elbe control build-cdroms [--build-bin|--build-sources] <project_dir>',
- file=sys.stderr)
- sys.exit(183)
-
- builddir = args[0]
- client.service.build_cdroms(builddir, opt.build_bin, opt.build_sources)
-
-
-ClientAction.register(BuildCDROMsAction)
-
-
-class GetFileAction(ClientAction):
-
- tag = 'get_file'
-
- def execute(self, client, opt, args):
- if len(args) != 2:
- print(
- 'usage: elbe control get_file <project_dir> <file>',
- file=sys.stderr)
- sys.exit(184)
-
- builddir = args[0]
- filename = args[1]
- dst_fname = filename
-
- if opt.output:
- dst = os.path.abspath(opt.output)
- os.makedirs(dst, exist_ok=True)
- dst_fname = str(os.path.join(dst, filename)).encode()
-
- client.download_file(builddir, filename, dst_fname)
- print(f'{dst_fname} saved')
-
-
-ClientAction.register(GetFileAction)
-
-
-class BuildChrootAction(ClientAction):
-
- tag = 'build_chroot_tarball'
-
- def execute(self, client, _opt, args):
- if len(args) != 1:
- print(
- 'usage: elbe control build_chroot_tarball <project_dir>',
- file=sys.stderr)
- sys.exit(185)
-
- builddir = args[0]
-
- client.service.build_chroot_tarball(builddir)
-
-
-ClientAction.register(BuildChrootAction)
-
-
-class DumpFileAction(ClientAction):
-
- tag = 'dump_file'
-
- def execute(self, client, _opt, args):
- if len(args) != 2:
- print(
- 'usage: elbe control dump_file <project_dir> <file>',
- file=sys.stderr)
- sys.exit(186)
-
- builddir = args[0]
- filename = args[1]
-
- part = 0
while True:
- ret = client.service.get_file(builddir, filename, part)
- if ret == 'FileNotFound':
- print(ret, file=sys.stderr)
- sys.exit(187)
- if ret == 'EndOfFile':
- return
-
- os.write(sys.stdout.fileno(), binascii.a2b_base64(ret))
- part = part + 1
-
-
-ClientAction.register(DumpFileAction)
-
-
-class GetFilesAction(ClientAction):
-
- tag = 'get_files'
-
- def execute(self, client, opt, args):
- if len(args) != 1:
- print(
- 'usage: elbe control get_files <project_dir>',
- file=sys.stderr)
- sys.exit(188)
-
- builddir = args[0]
- files = client.service.get_files(builddir)
-
- nfiles = 0
-
- for f in files[0]:
- if (opt.pbuilder_only and not f.name.startswith('pbuilder_cross')
- and not f.name.startswith('pbuilder')):
- continue
-
- if opt.matches and not fnmatch.fnmatch(f.name, opt.matches):
- continue
-
- nfiles += 1
- try:
- print(f'{f.name} \t({f.description})')
- except AttributeError:
- print(f'{f.name}')
- if opt.output:
- dst = os.path.abspath(opt.output)
- os.makedirs(dst, exist_ok=True)
- dst_fname = str(os.path.join(dst, os.path.basename(f.name)))
- client.download_file(builddir, f.name, dst_fname)
+ bin_data = f.read(size)
+ data = binascii.b2a_base64(bin_data)
- if nfiles == 0:
- sys.exit(189)
+ if not isinstance(data, str):
+ data = data.decode('ascii')
+ append(build_dir, data)
-ClientAction.register(GetFilesAction)
-
-
-class WaitProjectBusyAction(ClientAction):
-
- tag = 'wait_busy'
-
- def execute(self, client, _opt, args):
- if len(args) != 1:
- print(
- 'usage: elbe control wait_busy <project_dir>',
- file=sys.stderr)
- sys.exit(190)
-
- builddir = args[0]
-
- while True:
- try:
- msg = client.service.get_project_busy(builddir)
- # TODO the root cause of this problem is unclear. To enable a
- # get more information print the exception and retry to see if
- # the connection problem is just a temporary problem. This
- # code should be reworked as soon as it's clear what is going on
- # here
- except socket.error as e:
- print(str(e), file=sys.stderr)
- print('socket error during wait busy occured, retry..',
- file=sys.stderr)
- continue
-
- if not msg:
- time.sleep(0.1)
- continue
-
- if msg == 'ELBE-FINISH':
+ if len(bin_data) != size:
break
- print(msg)
- # exited the while loop -> the project is not busy anymore,
- # check, whether everything is ok.
+ at _add_project_dir_argument
+def _remove_log(client, args):
+ client.service.rm_log(args.project_dir)
- prj = client.service.get_project(builddir)
- if prj.status != 'build_done':
- print(
- 'Project build was not successful, current status: '
- f'{prj.status}',
- file=sys.stderr)
- sys.exit(191)
+def _list_projects(client, args):
+ projects = client.service.list_projects()
-ClientAction.register(WaitProjectBusyAction)
-
-
-class SetCdromAction(ClientAction):
-
- tag = 'set_cdrom'
-
- def execute(self, client, _opt, args):
-
- if len(args) != 2:
+ try:
+ for p in projects.SoapProject:
print(
- 'usage: elbe control set_cdrom <project_dir> <cdrom file>',
- file=sys.stderr)
- sys.exit(192)
+ f'{p.builddir}\t{p.name}\t{p.version}\t{p.status}\t'
+ f'{p.edit}')
+ except AttributeError:
+ print('No projects configured in initvm')
- builddir = args[0]
- filename = args[1]
-
- client.service.start_cdrom(builddir)
- self.upload_file(client.service.append_cdrom, builddir, filename)
- client.service.finish_cdrom(builddir)
-
-
-ClientAction.register(SetCdromAction)
-
-
-class SetOrigAction(ClientAction):
-
- tag = 'set_orig'
-
- def execute(self, client, _opt, args):
-
- if len(args) != 2:
- print(
- 'usage: elbe control set_orig <project_dir> <orig file>',
- file=sys.stderr)
- sys.exit(193)
-
- builddir = args[0]
- filename = args[1]
-
- client.service.start_upload_orig(builddir, os.path.basename(filename))
- self.upload_file(client.service.append_upload_orig, builddir, filename)
- client.service.finish_upload_orig(builddir)
-
-
-ClientAction.register(SetOrigAction)
+def _list_users(client, args):
+ users = client.service.list_users()
-class SetPdebuilderAction(ClientAction):
+ for u in users.string:
+ print(u)
- tag = 'set_pdebuild'
- def execute(self, client, opt, args):
+ at add_argument('name')
+ at add_argument('fullname')
+ at add_argument('password')
+ at add_argument('email')
+def _add_user(client, args):
+ try:
+ client.service.add_user(args.name, args.fullname, args.password, args.email, False)
+ except WebFault as e:
+ if not hasattr(e.fault, 'faultstring'):
+ raise
- if len(args) != 2 and len(args) != 3:
- print('usage: elbe control set_pdebuild '
- '<project_dir> <pdebuild file>', file=sys.stderr)
- sys.exit(195)
+ if not e.fault.faultstring.endswith('already exists in the database'):
+ raise
- builddir = args[0]
- filename = args[1]
-
- client.service.start_pdebuild(builddir)
- self.upload_file(client.service.append_pdebuild, builddir, filename)
- client.service.finish_pdebuild(builddir, opt.cpuset,
- opt.profile, opt.cross)
-
-
-ClientAction.register(SetPdebuilderAction)
+ # when we get here, the user we wanted to create already exists.
+ # that is fine, and we dont need to do anything now.
-class BuildPbuilderAction(ClientAction):
+def _create_project(client, args):
+ uuid = client.service.new_project()
+ print(uuid)
- tag = 'build_pbuilder'
- def execute(self, client, opt, args):
- if len(args) != 1:
- print(
- 'usage: elbe control build_pbuilder <project_dir>',
- file=sys.stderr)
- sys.exit(196)
+ at _add_project_dir_argument
+def _reset_project(client, args):
+ client.service.reset_project(args.project_dir)
- builddir = args[0]
- client.service.build_pbuilder(builddir, opt.cross, opt.noccache,
- opt.ccachesize)
+ at _add_project_dir_argument
+def _delete_project(client, args):
+ client.service.del_project(args.project_dir)
-ClientAction.register(BuildPbuilderAction)
+ at _add_project_dir_argument
+ at add_argument('xml')
+def _set_xml(client, args):
+ builddir = args.project_dir
+ filename = args.xml
-class UpdatePbuilderAction(ClientAction):
+ try:
+ x = ElbeXML(
+ filename,
+ skip_validate=True,
+ url_validation=ValidationMode.NO_CHECK)
+ except IOError:
+ print(f'{filename} is not a valid elbe xml file')
+ sys.exit(177)
- tag = 'update_pbuilder'
+ if not x.has('target'):
+ print("<target> is missing, this file can't be built in an initvm",
+ file=sys.stderr)
+ sys.exit(178)
- def execute(self, client, _opt, args):
- if len(args) != 1:
- print(
- 'usage: elbe control update_pbuilder <project_dir>',
- file=sys.stderr)
- sys.exit(197)
+ size = 1024 * 1024
+ part = 0
+ with open(filename, 'rb') as fp:
+ while True:
- builddir = args[0]
- client.service.update_pbuilder(builddir)
+ xml_base64 = binascii.b2a_base64(fp.read(size))
+
+ if not isinstance(xml_base64, str):
+ xml_base64 = xml_base64.decode('ascii')
+
+ # finish upload
+ if len(xml_base64) == 1:
+ part = client.service.upload_file(builddir,
+ 'source.xml',
+ xml_base64,
+ -1)
+ else:
+ part = client.service.upload_file(builddir,
+ 'source.xml',
+ xml_base64,
+ part)
+ if part == -1:
+ print('project busy, upload not allowed')
+ return part
+ if part == -2:
+ print('upload of xml finished')
+ return 0
+
+
+ at add_argument('--build-bin', action='store_true', dest='build_bin',
+ help='Build binary repository CDROM, for exact reproduction.')
+ at add_argument('--build-sources', action='store_true', dest='build_sources',
+ help='Build source CDROM')
+ at add_argument('--skip-pbuilder', action='store_true', dest='skip_pbuilder',
+ help="skip pbuilder section of XML (don't build packages)")
+ at _add_project_dir_argument
+def _build(client, args):
+ client.service.build(args.project_dir, args.build_bin, args.build_sources, args.skip_pbuilder)
+
+
+ at _add_project_dir_argument
+def _build_sysroot(client, args):
+ client.service.build_sysroot(args.project_dir)
+
+
+ at _add_project_dir_argument
+def _build_sdk(client, args):
+ client.service.build_sdk(args.project_dir)
+
+
+ at add_argument('--build-bin', action='store_true', dest='build_bin',
+ help='Build binary repository CDROM, for exact reproduction.')
+ at add_argument('--build-sources', action='store_true', dest='build_sources',
+ help='Build source CDROM')
+ at _add_project_dir_argument
+def _build_cdroms(client, args):
+ if not args.build_bin and not args.build_sources:
+ args.parser.error('One of --build-bin or --build-sources needs to be specified')
+
+ client.service.build_cdroms(args.project_dir, args.build_bin, args.build_sources)
+
+
+ at add_argument('--output', required=True, help='Output files to <directory>')
+ at _add_project_dir_argument
+ at add_argument('file')
+def _get_file(client, args):
+ dst = os.path.abspath(args.output)
+ os.makedirs(dst, exist_ok=True)
+ dst_fname = str(os.path.join(dst, args.file)).encode()
+
+ client.download_file(args.project_dir, args.file, dst_fname)
+ print(f'{args.file} saved')
+
+
+ at _add_project_dir_argument
+def _build_chroot(client, args):
+ client.service.build_chroot_tarball(args.project_dir)
+
+
+ at _add_project_dir_argument
+ at add_argument('file')
+def _dump_file(client, args):
+ part = 0
+ while True:
+ ret = client.service.get_file(args.project_dir, args.file, part)
+ if ret == 'FileNotFound':
+ print(ret, file=sys.stderr)
+ sys.exit(187)
+ if ret == 'EndOfFile':
+ return
+
+ os.write(sys.stdout.fileno(), binascii.a2b_base64(ret))
+ part = part + 1
+
+
+ at add_argument('--output', required=True, help='Output files to <directory>')
+ at add_argument('--pbuilder-only', action='store_true', dest='pbuilder_only',
+ help='Only list/download pbuilder Files')
+ at add_argument('--matches', dest='matches', default=False,
+ help='Select files based on wildcard expression.')
+ at _add_project_dir_argument
+def _get_files(client, args):
+ files = client.service.get_files(args.project_dir)
+
+ nfiles = 0
+
+ for f in files[0]:
+ if (args.pbuilder_only and not f.name.startswith('pbuilder_cross')
+ and not f.name.startswith('pbuilder')):
+ continue
+
+ if args.matches and not fnmatch.fnmatch(f.name, args.matches):
+ continue
+
+ nfiles += 1
+ try:
+ print(f'{f.name} \t({f.description})')
+ except AttributeError:
+ print(f'{f.name}')
+ dst = os.path.abspath(args.output)
+ os.makedirs(dst, exist_ok=True)
+ dst_fname = str(os.path.join(dst, os.path.basename(f.name)))
+ client.download_file(args.project_dir, f.name, dst_fname)
-ClientAction.register(UpdatePbuilderAction)
+ if nfiles == 0:
+ sys.exit(189)
-class RepoAction(ClientAction):
+ at _add_project_dir_argument
+def _wait_busy(client, args):
+ while True:
+ try:
+ msg = client.service.get_project_busy(args.project_dir)
+ # TODO the root cause of this problem is unclear. To enable a
+ # get more information print the exception and retry to see if
+ # the connection problem is just a temporary problem. This
+ # code should be reworked as soon as it's clear what is going on
+ # here
+ except socket.error as e:
+ print(str(e), file=sys.stderr)
+ print('socket error during wait busy occured, retry..',
+ file=sys.stderr)
+ continue
+
+ if not msg:
+ time.sleep(0.1)
+ continue
+
+ if msg == 'ELBE-FINISH':
+ break
+
+ print(msg)
+
+ # exited the while loop -> the project is not busy anymore,
+ # check, whether everything is ok.
+
+ prj = client.service.get_project(args.project_dir)
+ if prj.status != 'build_done':
+ print(
+ 'Project build was not successful, current status: '
+ f'{prj.status}',
+ file=sys.stderr)
+ sys.exit(191)
+
+
+ at _add_project_dir_argument
+ at add_argument('cdrom_file')
+def _set_cdrom(client, args):
+ client.service.start_cdrom(args.project_dir)
+ _client_action_upload_file(client.service.append_cdrom, args.project_dir, args.cdrom_file)
+ client.service.finish_cdrom(args.project_dir)
+
+
+ at _add_project_dir_argument
+ at add_argument('orig_file')
+def _set_orig(client, args):
+ client.service.start_upload_orig(args.project_dir, os.path.basename(args.orig_file))
+ _client_action_upload_file(client.service.append_upload_orig, args.project_dir, args.orig_file)
+ client.service.finish_upload_orig(args.project_dir)
+
+
+ at add_argument('--profile', dest='profile', default='',
+ help='Make pbuilder commands build the specified profile')
+ at add_argument('--cross', dest='cross', action='store_true',
+ help='Creates an environment for crossbuilding if '
+ 'combined with create. Combined with build it'
+ ' will use this environment.')
+ at add_argument('--cpuset', default=-1, type=int,
+ help='Limit cpuset of pbuilder commands (bitmask)'
+ '(defaults to -1 for all CPUs)')
+ at _add_project_dir_argument
+ at add_argument('pdebuild_file')
+def _set_pdebuild(client, args):
+ client.service.start_pdebuild(args.project_dir)
+ _client_action_upload_file(client.service.append_pdebuild, args.project_dir, args.pdebuild_file)
+ client.service.finish_pdebuild(args.project_dir, args.cpuset, args.profile, args.cross)
+
+
+ at add_argument('--cross', dest='cross', action='store_true',
+ help='Creates an environment for crossbuilding if '
+ 'combined with create. Combined with build it'
+ ' will use this environment.')
+ at add_argument('--no-ccache', dest='noccache', action='store_true',
+ help="Deactivates the compiler cache 'ccache'")
+ at add_argument('--ccache-size', dest='ccachesize', default='10G',
+ help='set a limit for the compiler cache size '
+ '(should be a number followed by an optional '
+ 'suffix: k, M, G, T. Use 0 for no limit.)')
+ at _add_project_dir_argument
+def _build_pbuilder(client, args):
+ client.service.build_pbuilder(args.project_dir, args.cross, args.noccache, args.ccachesize)
+
+
+ at _add_project_dir_argument
+def _update_pbuilder(client, args):
+ client.service.update_pbuilder(args.project_dir)
+
+
+client_actions = {
+ 'rm_log': _remove_log,
+ 'list_projects': _list_projects,
+ 'list_users': _list_users,
+ 'add_user': _add_user,
+ 'create_project': _create_project,
+ 'reset_project': _reset_project,
+ 'del_project': _delete_project,
+ 'set_xml': _set_xml,
+ 'build': _build,
+ 'build_sysroot': _build_sysroot,
+ 'build_sdk': _build_sdk,
+ 'build_cdroms': _build_cdroms,
+ 'get_file': _get_file,
+ 'build_chroot_tarball': _build_chroot,
+ 'dump_file': _dump_file,
+ 'get_files': _get_files,
+ 'wait_busy': _wait_busy,
+ 'set_cdrom': _set_cdrom,
+ 'set_orig': _set_orig,
+ 'set_pdebuild': _set_pdebuild,
+ 'build_pbuilder': _build_pbuilder,
+ 'update_pbuilder': _update_pbuilder,
+}
+
+
+class RepoAction:
repoactiondict = {}
@classmethod
--
2.45.2
More information about the elbe-devel
mailing list