From ab8c5d16929d5d944d4d01d5b22590a879a8b1bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Schr=C3=B6ter?= Date: Thu, 29 Sep 2022 16:46:41 +0200 Subject: [PATCH] add create-pbuild-config(cpc) command which allows to create a working config for pbuild tool based on OBS server side data The cross build support is not yet done --- NEWS | 4 ++++ osc/commandline.py | 29 +++++++++++++++++++++++++++++ osc/core.py | 33 +++++++++++++++++++++++++++++++++ osc/oscerr.py | 9 +++++++++ 4 files changed, 75 insertions(+) diff --git a/NEWS b/NEWS index f6ec0d4e..088dde01 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,7 @@ +1.0.0b3 + - add create-pbuild-config(cpc) command which allows to create a working + config for pbuild tool based on OBS server side data + 1.0.0b2 - Support ssh-agent forwarding - ssh auth: Avoid password prompt when using TransientCredentialsManager diff --git a/osc/commandline.py b/osc/commandline.py index 0cef868f..79f58036 100644 --- a/osc/commandline.py +++ b/osc/commandline.py @@ -8345,6 +8345,35 @@ Please submit there instead, or use --nodevelproject to force direct submission. if len(user) == 3: print("%s: \"%s\" <%s>" % (user[0], user[1], user[2])) + @cmdln.name("create-pbuild-config") + @cmdln.alias('cpc') + @cmdln.option("repository") + @cmdln.option("arch") + def do_create_pbuild_config(self, subcmd, opts): + """ + This command is creating the necessary files to build using pbuild tool. + It basically creates _config and _pbuild file in the project directory. + Changes from there can not get submitted back, except the project is managed + in git. + + Examples: + osc cpc REPOSITORY ARCH + """ + + apiurl = self.get_api_url() + project = None + project_dir = os.curdir + if is_project_dir(project_dir): + project = store_read_project(project_dir) + elif is_package_dir(project_dir): + project_dir += '/..' + project = store_read_project(project_dir) + else: + raise oscerr.WrongArgs('Creating pbuild only works in a checked out project or package') + + create_pbuild_config(apiurl, project, opts.repository, opts.arch, project_dir) + + @cmdln.option('-r', '--revision', metavar='rev', help='print out the specified revision') @cmdln.option('-e', '--expand', action='store_true', diff --git a/osc/core.py b/osc/core.py index 9c279339..fd7a1cee 100644 --- a/osc/core.py +++ b/osc/core.py @@ -6379,6 +6379,39 @@ def get_buildconfig(apiurl, prj, repository, path=None): return f.read() +def create_pbuild_config(apiurl, project, repository, arch, project_dir): + """ + This is always replacing a possible exiting config for now + we could extend the _pbuild file easily, but what should we do with multiple instances of the _config? + """ + # get expanded buildconfig for given project and repository + bc = get_buildconfig(apiurl, project, repository) + if not bc: + msg = "Failed to get build config for project '{project}', repository '{repository}'" + raise oscerr.NotFoundAPIError(msg) + + with open(os.path.join(project_dir, '_config'), "w") as f: + f.write(decode_it(bc)) + + # create the _pbuild file based on expanded repository path informations + pb = ET.fromstring('') + tree = ET.ElementTree(pb) + preset = ET.SubElement(pb, 'preset', name=repository, default="") # default should be empty, but ET crashes + bi_text = decode_it(get_buildinfo(apiurl, project, '_repository', repository, arch, specfile="Name: dummy")) + root = ET.fromstring(bi_text) + +# cross compile setups are not yet supported +# for path in root.findall('hostsystem'): +# ET.SubElement(preset, 'hostrepo').text = path.get('url') + + for path in root.findall('path'): + ET.SubElement(preset, 'repo').text = path.get('url') + + ET.SubElement(preset, 'arch').text = arch + xmlindent(tree) + tree.write(os.path.join(project_dir,'_pbuild'), encoding="utf-8", xml_declaration=True) + + def get_worker_info(apiurl, worker): u = makeurl(apiurl, ['worker', worker]) f = http_GET(u) diff --git a/osc/oscerr.py b/osc/oscerr.py index 9df3de89..7441d99f 100644 --- a/osc/oscerr.py +++ b/osc/oscerr.py @@ -50,6 +50,15 @@ class APIError(OscBaseError): super().__init__() self.msg = msg + def __str__(self): + return f"{self.__class__.__name__}: {self.msg}" + + +class NotFoundAPIError(APIError): + """ + Requested data was not found. + """ + class NoConfigfile(OscBaseError): """Exception raised when osc's configfile cannot be found"""