Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package osc for openSUSE:Factory checked in at 2024-04-15 20:18:17 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/osc (Old) and /work/SRC/openSUSE:Factory/.osc.new.26366 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "osc" Mon Apr 15 20:18:17 2024 rev:194 rq:1167781 version:1.6.2 Changes: -------- --- /work/SRC/openSUSE:Factory/osc/osc.changes 2024-03-21 17:02:18.432550465 +0100 +++ /work/SRC/openSUSE:Factory/.osc.new.26366/osc.changes 2024-04-15 20:24:24.733772883 +0200 @@ -1,0 +2,21 @@ +Mon Apr 15 08:32:49 UTC 2024 - Daniel Mach <daniel.m...@suse.com> + +- 1.6.2 + - Command-line: + - Fix 'branch' command to allow using '--new-package' option on packages that do not exist + - Fix 'buildinfo' command to include obs:cli_debug_packages by default + - Fix 'buildinfo' command to send complete local build environment as the 'build' command does + - Allow `osc rpmlint` to infer prj/pkg from CWD + - Propagate exit code from the run() and do_() commandline methods + - Give a hint where a scmsync git is hosted + - Fix crash in 'updatepacmetafromspec' command when working with an incomplete spec + - Authentication: + - Cache password from SecretService to avoid spamming user with an accept dialog + - Never ask for credentials when displaying help + - Library: + - Support package linking of packages from scmsync projects + - Fix do_createrequest() function to return None instead of request id + - Replace invalid 'if' with 'elif' in BaseModel.dict() + - Fix crash when no prefered packages are defined + +------------------------------------------------------------------- Old: ---- osc-1.6.1.tar.gz New: ---- osc-1.6.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ osc.spec ++++++ --- /var/tmp/diff_new_pack.ysphS7/_old 2024-04-15 20:24:25.429798509 +0200 +++ /var/tmp/diff_new_pack.ysphS7/_new 2024-04-15 20:24:25.433798656 +0200 @@ -62,7 +62,7 @@ %endif Name: osc -Version: 1.6.1 +Version: 1.6.2 Release: 0 Summary: Command-line client for the Open Build Service License: GPL-2.0-or-later ++++++ PKGBUILD ++++++ --- /var/tmp/diff_new_pack.ysphS7/_old 2024-04-15 20:24:25.457799540 +0200 +++ /var/tmp/diff_new_pack.ysphS7/_new 2024-04-15 20:24:25.461799687 +0200 @@ -1,6 +1,6 @@ pkgname=osc -pkgver=1.6.1 -pkgrel=0 +pkgver=1.6.2 +pkgrel=842d44ef6b89b2433bab2759a04b940f pkgdesc="Command-line client for the Open Build Service" arch=('x86_64') url="https://www.github.com/openSUSE/osc" ++++++ debian.changelog ++++++ --- /var/tmp/diff_new_pack.ysphS7/_old 2024-04-15 20:24:25.497801013 +0200 +++ /var/tmp/diff_new_pack.ysphS7/_new 2024-04-15 20:24:25.501801159 +0200 @@ -1,4 +1,4 @@ -osc (1.6.1-0) unstable; urgency=low +osc (1.6.2-0) unstable; urgency=low * Placeholder ++++++ osc-1.6.1.tar.gz -> osc-1.6.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.6.1/NEWS new/osc-1.6.2/NEWS --- old/osc-1.6.1/NEWS 2024-02-23 09:45:57.000000000 +0100 +++ new/osc-1.6.2/NEWS 2024-04-15 10:30:30.000000000 +0200 @@ -1,3 +1,21 @@ +- 1.6.2 + - Command-line: + - Fix 'branch' command to allow using '--new-package' option on packages that do not exist + - Fix 'buildinfo' command to include obs:cli_debug_packages by default + - Fix 'buildinfo' command to send complete local build environment as the 'build' command does + - Allow `osc rpmlint` to infer prj/pkg from CWD + - Propagate exit code from the run() and do_() commandline methods + - Give a hint where a scmsync git is hosted + - Fix crash in 'updatepacmetafromspec' command when working with an incomplete spec + - Authentication: + - Cache password from SecretService to avoid spamming user with an accept dialog + - Never ask for credentials when displaying help + - Library: + - Support package linking of packages from scmsync projects + - Fix do_createrequest() function to return None instead of request id + - Replace invalid 'if' with 'elif' in BaseModel.dict() + - Fix crash when no prefered packages are defined + - 1.6.1 - Command-line: - Use busybox compatible commands for completion diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.6.1/osc/__init__.py new/osc-1.6.2/osc/__init__.py --- old/osc-1.6.1/osc/__init__.py 2024-02-23 09:45:57.000000000 +0100 +++ new/osc-1.6.2/osc/__init__.py 2024-04-15 10:30:30.000000000 +0200 @@ -13,7 +13,7 @@ from .util import git_version -__version__ = git_version.get_version('1.6.1') +__version__ = git_version.get_version('1.6.2') # vim: sw=4 et diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.6.1/osc/build.py new/osc-1.6.2/osc/build.py --- old/osc-1.6.1/osc/build.py 2024-02-23 09:45:57.000000000 +0100 +++ new/osc-1.6.2/osc/build.py 2024-04-15 10:30:30.000000000 +0200 @@ -11,8 +11,9 @@ import shutil import subprocess import sys - from tempfile import NamedTemporaryFile, mkdtemp +from typing import List +from typing import Optional from urllib.parse import urlsplit from urllib.request import URLError, HTTPError from xml.etree import ElementTree as ET @@ -481,7 +482,6 @@ return None - def get_prefer_pkgs(dirs, wanted_arch, type, cpio): paths = [] repositories = [] @@ -670,6 +670,76 @@ return run_external(cmd[0], *cmd[1:]) +def create_build_descr_data( + build_descr_path: Optional[str], + *, + build_type: Optional[str], + repo: Optional[str] = None, + arch: Optional[str] = None, + prefer_pkgs: Optional[List[str]] = None, + define: Optional[List[str]] = None, + define_with: Optional[List[str]] = None, + define_without: Optional[List[str]] = None, +): + if build_descr_path: + build_descr_path = os.path.abspath(build_descr_path) + topdir = os.path.dirname(build_descr_path) + else: + topdir = None + result_data = [] + + if build_descr_path: + print(f"Using local file: {os.path.basename(build_descr_path)}", file=sys.stderr) + with open(build_descr_path, "rb") as f: + build_descr_data = f.read() + + # HACK: there's no api to provide custom defines + # TODO: check if we're working with a spec? + defines: List[bytes] = [] + for i in define or []: + defines.append(f"%define {i}".encode("utf-8")) + for i in define_with or []: + defines.append(f"%define _with_{i} 1".encode("utf-8")) + for i in define_without or []: + defines.append(f"%define _without_{i} 1".encode("utf-8")) + if defines: + build_descr_data = b"\n".join(defines) + b"\n\n" + build_descr_data + + # build recipe must go first for compatibility with the older OBS versions + result_data.append((os.path.basename(build_descr_path).encode("utf-8"), build_descr_data)) + + if topdir: + buildenv_file = os.path.join(topdir, f"_buildenv.{repo}.{arch}") + if not os.path.isfile(buildenv_file): + buildenv_file = os.path.join(topdir, f"_buildenv") + if os.path.isfile(buildenv_file): + print(f"Using local file: {os.path.basename(buildenv_file)}", file=sys.stderr) + with open(buildenv_file, "rb") as f: + result_data.append((b"buildenv", f.read())) + + if topdir: + service_file = os.path.join(topdir, "_service") + if os.path.isfile(service_file): + print("Using local file: _service", file=sys.stderr) + with open(service_file, "rb") as f: + result_data.append((b"_service", f.read())) + + if not result_data and not prefer_pkgs: + return None, None + + cpio_data = cpio.CpioWrite() + for key, value in result_data: + cpio_data.add(key, value) + + if prefer_pkgs: + print("Scanning the following dirs for local preferred packages: {', '.join(dirs)}", file=sys.stderr) + prefer_pkgs_result = get_prefer_pkgs(prefer_pkgs, arch, build_type, cpio_data) + else: + prefer_pkgs_result = {} + + return cpio_data.get(), prefer_pkgs_result + + def main(apiurl, store, opts, argv): repo = argv[0] @@ -898,59 +968,16 @@ if xp: extra_pkgs += xp - prefer_pkgs = {} - build_descr_data = open(build_descr, 'rb').read() - - # XXX: dirty hack but there's no api to provide custom defines - if opts.without: - s = '' - for i in opts.without: - s += "%%define _without_%s 1\n" % i - build_descr_data = s.encode() + build_descr_data - if opts._with: - s = '' - for i in opts._with: - s += "%%define _with_%s 1\n" % i - build_descr_data = s.encode() + build_descr_data - if opts.define: - s = '' - for i in opts.define: - s += "%%define %s\n" % i - build_descr_data = s.encode() + build_descr_data - - cpiodata = None - servicefile = os.path.join(os.path.dirname(build_descr), "_service") - if not os.path.isfile(servicefile): - servicefile = os.path.join(os.path.dirname(build_descr), "_service") - if not os.path.isfile(servicefile): - servicefile = None - else: - print('Using local _service file') - buildenvfile = os.path.join(os.path.dirname(build_descr), "_buildenv." + repo + "." + arch) - if not os.path.isfile(buildenvfile): - buildenvfile = os.path.join(os.path.dirname(build_descr), "_buildenv") - if not os.path.isfile(buildenvfile): - buildenvfile = None - else: - print('Using local buildenv file: %s' % os.path.basename(buildenvfile)) - if buildenvfile or servicefile: - if not cpiodata: - cpiodata = cpio.CpioWrite() - - if opts.prefer_pkgs: - print('Scanning the following dirs for local packages: %s' % ', '.join(opts.prefer_pkgs)) - if not cpiodata: - cpiodata = cpio.CpioWrite() - prefer_pkgs = get_prefer_pkgs(opts.prefer_pkgs, arch, build_type, cpiodata) - - if cpiodata: - cpiodata.add(os.path.basename(build_descr.encode()), build_descr_data) - # buildenv must come last for compatibility reasons... - if buildenvfile: - cpiodata.add(b"buildenv", open(buildenvfile, 'rb').read()) - if servicefile: - cpiodata.add(b"_service", open(servicefile, 'rb').read()) - build_descr_data = cpiodata.get() + build_descr_data, prefer_pkgs = create_build_descr_data( + build_descr, + build_type=build_type, + repo=repo, + arch=arch, + prefer_pkgs=opts.prefer_pkgs, + define=opts.define, + define_with=opts._with, + define_without=opts.without, + ) # special handling for overlay and rsync-src/dest specialcmdopts = [] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.6.1/osc/commandline.py new/osc-1.6.2/osc/commandline.py --- old/osc-1.6.1/osc/commandline.py 2024-02-23 09:45:57.000000000 +0100 +++ new/osc-1.6.2/osc/commandline.py 2024-04-15 10:30:30.000000000 +0200 @@ -21,6 +21,7 @@ from functools import cmp_to_key from operator import itemgetter from pathlib import Path +from tempfile import NamedTemporaryFile from typing import List from urllib.parse import urlsplit from urllib.error import HTTPError @@ -243,7 +244,7 @@ if not cmd: self.parser.error("Please specify a command") self.post_parse_args(args) - cmd.run(args) + return cmd.run(args) def load_command(self, cls, module_prefix): mod_cls_name = f"{module_prefix}.{cls.__name__}" @@ -410,6 +411,10 @@ ) def post_parse_args(self, args): + if args.command == "help": + # HACK: never ask for credentials when displaying help + return + # apiurl hasn't been specified by the user # we need to set it here because the 'default' option of an argument doesn't support lazy evaluation if args.apiurl is None: @@ -496,10 +501,10 @@ # handler doesn't take positional args via *args if args.positional_args: self.parser.error(f"unrecognized arguments: " + " ".join(args.positional_args)) - self.func(args.command, args) + return self.func(args.command, args) else: # handler takes positional args via *args - self.func(args.command, args, *args.positional_args) + return self.func(args.command, args, *args.positional_args) return LegacyCommandWrapper @@ -555,7 +560,8 @@ cmd.load_legacy_commands() if run: args = cmd.parse_args(args=argv) - cmd.run(args) + exit_code = cmd.run(args) + sys.exit(exit_code) else: args = None return cmd, args @@ -2821,7 +2827,6 @@ for srid in supersede: change_request_state(apiurl, srid, 'superseded', f'superseded by {rid}', rid) - return rid @cmdln.option('-m', '--message', metavar='TEXT', help='specify message TEXT') @@ -5777,6 +5782,7 @@ prj = Project(arg, progress_obj=self.download_progress) if prj.scm_url: print("Please use git to update project", prj.name) + print("This git repository is hosted at", prj.scm_url) continue if conf.config['do_package_tracking']: @@ -5841,6 +5847,7 @@ # sys.exit(1) if p.scm_url: print("Please use git to update package", p.name) + print("This git repository is hosted at", p.scm_url) continue if not rev: @@ -6206,7 +6213,23 @@ apiurl = self.get_api_url() args = slash_split(args) - if len(args) == 4: + if len(args) <= 3: + project = store_read_project(Path.cwd()) + package = store_read_package(Path.cwd()) + if len(args) == 1: + repository, arch = self._find_last_repo_arch(args[0], fatal=False) + if repository is None: + # no local build with this repo was done + print('failed to guess arch, using hostarch') + repository = args[0] + arch = osc_build.hostarch + elif len(args) == 2: + repository, arch = args + elif len(args) == 3: + raise oscerr.WrongArgs('Too many arguments.') + else: # len(args) = 0 case + self.print_repos() + elif len(args) == 4: project, package, repository, arch = args else: raise oscerr.WrongArgs('please provide project package repository arch.') @@ -6626,6 +6649,8 @@ help='Add this package when computing the buildinfo') @cmdln.option('-p', '--prefer-pkgs', metavar='DIR', action='append', help='Prefer packages from this directory when installing the build-root') + @cmdln.option('--nodebugpackages', '--no-debug-packages', action='store_true', + help='Skip installation of additional debug packages for CLI builds (specified in obs:cli_debug_packages in project metadata)') def do_buildinfo(self, subcmd, opts, *args): """ Shows the build info @@ -6685,28 +6710,50 @@ apiurl = self.get_api_url() - build_descr_data = None - if build_descr is not None: - build_descr_data = open(build_descr, 'rb').read() - if opts.prefer_pkgs and build_descr_data is None: - raise oscerr.WrongArgs('error: a build description is needed if \'--prefer-pkgs\' is used') - elif opts.prefer_pkgs: - print(f"Scanning the following dirs for local packages: {', '.join(opts.prefer_pkgs)}") - cpiodata = cpio.CpioWrite() - prefer_pkgs = osc_build.get_prefer_pkgs(opts.prefer_pkgs, arch, - os.path.splitext(build_descr)[1], - cpiodata) - cpiodata.add(os.path.basename(build_descr.encode()), build_descr_data) - build_descr_data = cpiodata.get() + # TODO: refactor retrieving build type in build.py and use it here or directly in create_build_descr_data() + if build_descr: + build_type = os.path.splitext(build_descr)[1] + else: + build_type = None + + build_descr_data, prefer_pkgs = osc_build.create_build_descr_data( + build_descr, + build_type=build_type, + repo=repository, + arch=arch, + prefer_pkgs=opts.prefer_pkgs, + # define=, + # define_with=, + # define_without=, + ) if opts.multibuild_package: package = package + ":" + opts.multibuild_package - print(decode_it(get_buildinfo(apiurl, - project, package, repository, arch, - specfile=build_descr_data, - debug=opts.debug_dependencies, - addlist=opts.extra_pkgs))) + extra_pkgs = opts.extra_pkgs.copy() if opts.extra_pkgs else [] + + if os.path.exists("/usr/lib/build/queryconfig") and not opts.nodebugpackages: + with NamedTemporaryFile(mode="w+b", prefix="obs_buildconfig_") as bc_file: + # print('Getting buildconfig from server and store to %s' % bc_filename) + bc = get_buildconfig(apiurl, project, repository) + bc_file.write(bc) + bc_file.flush() + + debug_pkgs = decode_it(return_external("/usr/lib/build/queryconfig", "--dist", bc_file.name, "substitute", "obs:cli_debug_packages")) + if debug_pkgs: + extra_pkgs.extend(debug_pkgs.strip().split(" ")) + + buildinfo = get_buildinfo( + apiurl, + project, + package, + repository, + arch, + specfile=build_descr_data, + debug=opts.debug_dependencies, + addlist=extra_pkgs, + ) + print(decode_it(buildinfo)) def do_buildconfig(self, subcmd, opts, *args): """ @@ -7075,7 +7122,7 @@ @cmdln.option('--no-verify', '--noverify', action='store_true', help='Skip signature verification (via pgp keys) of packages used for build. (Global config in oscrc: no_verify)') @cmdln.option('--nodebugpackages', '--no-debug-packages', action='store_true', - help='Skip installation of additional debug packages for CLI builds') + help='Skip installation of additional debug packages for CLI builds (specified in obs:cli_debug_packages in project metadata)') @cmdln.option("--skip-local-service-run", "--noservice", "--no-service", default=False, action="store_true", help="Skip run of local source services as specified in _service file.") @cmdln.option('-p', '--prefer-pkgs', metavar='DIR', action='append', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.6.1/osc/core.py new/osc-1.6.2/osc/core.py --- old/osc-1.6.1/osc/core.py 2024-02-23 09:45:57.000000000 +0100 +++ new/osc-1.6.2/osc/core.py 2024-04-15 10:30:30.000000000 +0200 @@ -4375,8 +4375,10 @@ section_pat = r'^%s\s*?$' for section in sections: m = re.compile(section_pat % section, re.I | re.M).search(''.join(lines)) - if m: - start = lines.index(m.group() + '\n') + 1 + if m is None: + spec_data[section] = "" + continue + start = lines.index(m.group() + '\n') + 1 data = [] for line in lines[start:]: if line.startswith('%'): @@ -5838,12 +5840,17 @@ elm.clear() ET.SubElement(elm, 'disable') + root.remove('scmsync') + dst_meta = ET.tostring(root, encoding=ET_ENCODING) if meta_change: + root = ET.fromstring(''.join(dst_meta)) + for scmsync in root.findall('scmsync'): + root.remove(scmsync) edit_meta('pkg', path_args=(dst_project, dst_package), - data=dst_meta) + data=ET.tostring(root, encoding=ET_ENCODING)) # create the _link file # but first, make sure not to overwrite an existing one if '_link' in meta_get_filelist(apiurl, dst_project, dst_package): @@ -6119,12 +6126,18 @@ # BEGIN: Error out on branching scmsync packages; this should be properly handled in the API # read src_package meta - m = b"".join(show_package_meta(apiurl, src_project, src_package)) - root = ET.fromstring(m) + try: + m = b"".join(show_package_meta(apiurl, src_project, src_package)) + root = ET.fromstring(m) + except HTTPError as e: + if e.code == 404 and missingok: + root = None + else: + raise devel_project = None devel_package = None - if not nodevelproject: + if root is not None and not nodevelproject: devel_node = root.find("devel") if devel_node is not None: devel_project = devel_node.get("project") @@ -6135,7 +6148,7 @@ root = ET.fromstring(m) # error out if we're branching a scmsync package (we'd end up with garbage anyway) - if root.find("scmsync") is not None: + if root is not None and root.find("scmsync") is not None: msg = "Cannot branch a package with <scmsync> set." if devel_project: raise oscerr.PackageError(devel_project, devel_package, msg) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.6.1/osc/credentials.py new/osc-1.6.2/osc/credentials.py --- old/osc-1.6.1/osc/credentials.py 2024-02-23 09:45:57.000000000 +0100 +++ new/osc-1.6.2/osc/credentials.py 2024-04-15 10:30:30.000000000 +0200 @@ -189,6 +189,10 @@ class KeyringCredentialsManager(AbstractCredentialsManager): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self._password = None + def _process_options(self, options): if options is None: raise RuntimeError('options may not be None') @@ -209,14 +213,19 @@ return super().create(cp, options) def _get_password(self, url, user, apiurl=None): - self._load_backend() - return keyring.get_password(urlsplit(url)[1], user) + if self._password is None: + self._load_backend() + self._password = keyring.get_password(urlsplit(url)[1], user) + # TODO: this works fine on the command-line but a long-running process using osc library would start failing after changing the password in the keyring + # TODO: implement retrieving the password again after basic auth fails; sufficiently inform user about what's being done + return self._password def set_password(self, url, user, password): self._load_backend() keyring.set_password(urlsplit(url)[1], user, password) config_value = f"{self._qualified_name()}:{self._backend_cls_name}" self._cp.set(url, self.config_entry, config_value) + self._password = password def delete_password(self, url, user): self._load_backend() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.6.1/osc/util/git_version.py new/osc-1.6.2/osc/util/git_version.py --- old/osc-1.6.1/osc/util/git_version.py 2024-02-23 09:45:57.000000000 +0100 +++ new/osc-1.6.2/osc/util/git_version.py 2024-04-15 10:30:30.000000000 +0200 @@ -9,7 +9,7 @@ """ # the `version` variable contents get substituted during `git archive` # it requires adding this to .gitattributes: <path to this file> export-subst - version = "1.6.1" + version = "1.6.2" if version.startswith(("$", "%")): # "$": version hasn't been substituted during `git archive` # "%": "Format:" and "$" characters get removed from the version string (a GitHub bug?) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/osc-1.6.1/osc/util/models.py new/osc-1.6.2/osc/util/models.py --- old/osc-1.6.1/osc/util/models.py 2024-02-23 09:45:57.000000000 +0100 +++ new/osc-1.6.2/osc/util/models.py 2024-04-15 10:30:30.000000000 +0200 @@ -384,7 +384,7 @@ value = getattr(self, name) if value is not None and field.is_model: result[name] = value.dict() - if value is not None and field.is_model_list: + elif value is not None and field.is_model_list: result[name] = [i.dict() for i in value] else: result[name] = value ++++++ osc.dsc ++++++ --- /var/tmp/diff_new_pack.ysphS7/_old 2024-04-15 20:24:25.869814709 +0200 +++ /var/tmp/diff_new_pack.ysphS7/_new 2024-04-15 20:24:25.877815003 +0200 @@ -1,6 +1,6 @@ Format: 1.0 Source: osc -Version: 1.6.1-0 +Version: 1.6.2-0 Binary: osc Maintainer: Adrian Schroeter <adr...@suse.de> Architecture: any