From 3b05c4586c6064fb310c0084d0a607daf7def97b Mon Sep 17 00:00:00 2001 From: Daniel Braunwarth Date: Fri, 26 Jun 2026 08:44:42 +0200 Subject: [PATCH 1/3] elbepack: main: mark import_cmd_module() as tree-wide usable Signed-off-by: Daniel Braunwarth --- elbepack/main.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/elbepack/main.py b/elbepack/main.py index 972986b55..47163385c 100644 --- a/elbepack/main.py +++ b/elbepack/main.py @@ -18,7 +18,7 @@ def get_cmdlist(): return [x for _, x, _ in pkgutil.iter_modules(elbepack.commands.__path__)] -def _import_cmd_module(cmd): +def import_cmd_module(cmd): return importlib.import_module('.' + cmd, elbepack.commands.__name__) @@ -37,7 +37,7 @@ def main(argv=sys.argv): logging.basicConfig() logging.getLogger('suds').setLevel(logging.WARNING) - cmdmod = _import_cmd_module(args.cmd) + cmdmod = import_cmd_module(args.cmd) try: cmdmod.run_command(cmd_argv) @@ -48,5 +48,5 @@ def main(argv=sys.argv): def run_elbe_subcommand(argv): - cmdmod = _import_cmd_module(argv[0]) + cmdmod = import_cmd_module(argv[0]) return cmdmod.run_command([os.fspath(arg) for arg in argv[1:]]) From 3f8755c2052e373c30f8ec7dca0b23610caa36f6 Mon Sep 17 00:00:00 2001 From: Daniel Braunwarth Date: Thu, 11 Jun 2026 19:21:42 +0200 Subject: [PATCH 2/3] elbepack: cyclonedx-sbom: add tests for repository URL parsing This patch adds tests for the already supported URLs. This enables us to easily refactor the current implementation and extend it for further URL formats. Signed-off-by: Daniel Braunwarth --- .../tests/cyclonedx/test_cyclonedx_sbom.py | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/elbepack/tests/cyclonedx/test_cyclonedx_sbom.py b/elbepack/tests/cyclonedx/test_cyclonedx_sbom.py index b05864f64..79981678f 100644 --- a/elbepack/tests/cyclonedx/test_cyclonedx_sbom.py +++ b/elbepack/tests/cyclonedx/test_cyclonedx_sbom.py @@ -10,6 +10,8 @@ import jsonschema +import pytest + try: import jsonschema._validators @@ -33,7 +35,7 @@ def _extras_msg(extras): from jsonschema.validators import RefResolver -from elbepack.main import run_elbe_subcommand +from elbepack.main import import_cmd_module, run_elbe_subcommand here = pathlib.Path(__file__).parent @@ -76,3 +78,24 @@ def test_reference_data(): reference_errors = here.joinpath('cyclonedx_reference.json.errors').read_text() assert error_report == reference_errors + + +@pytest.mark.parametrize('uri, expected_repository_url', [ + ( + 'http://deb.debian.org/debian/pool/a/adduser/adduser_3.134_all.deb', + 'http://deb.debian.org/debian', + ), + ( + 'http://deb.debian.org/debian/pool/main/a/adduser/adduser_3.134_all.deb', + 'http://deb.debian.org/debian', + ), + ( + 'http://deb.debian.org/debian-security/pool/updates/main/u/util-linux/' + 'bsdutils_2.38.1-5%2bdeb12u1_amd64.deb', + 'http://deb.debian.org/debian-security', + ), +]) +def test_repository_url_examples(uri, expected_repository_url): + cyclonedx_sbom = import_cmd_module('cyclonedx-sbom') + + assert cyclonedx_sbom._repository_url(uri) == expected_repository_url From 4241006f7106eb195c66818aaf09d9b8b87a81d6 Mon Sep 17 00:00:00 2001 From: Daniel Braunwarth Date: Thu, 11 Jun 2026 19:23:47 +0200 Subject: [PATCH 3/3] elbepack: cyclonedx-sbom: add support for flat repository layouts This brings support for repositories using a flat layout (e.g. minidinst). Signed-off-by: Daniel Braunwarth --- elbepack/commands/cyclonedx-sbom.py | 31 ++++++++++--------- .../tests/cyclonedx/test_cyclonedx_sbom.py | 4 +++ newsfragments/+scyclonedx-sbom-flat-repos.rst | 1 + 3 files changed, 22 insertions(+), 14 deletions(-) create mode 100644 newsfragments/+scyclonedx-sbom-flat-repos.rst diff --git a/elbepack/commands/cyclonedx-sbom.py b/elbepack/commands/cyclonedx-sbom.py index 21e5b23ab..496c5d0bd 100644 --- a/elbepack/commands/cyclonedx-sbom.py +++ b/elbepack/commands/cyclonedx-sbom.py @@ -49,20 +49,23 @@ def _remove_empty_fields(dict): def _repository_url(uri): - uri_parts = uri.split('/') - if len(uri_parts) < 6: - raise ValueError('URI needs to be in pool layout') - if uri_parts[-4] == 'pool': - # http://deb.debian.org/debian/pool/a/adduser/adduser_3.134_all.deb - return '/'.join(uri_parts[:-4]) - elif uri_parts[-5] == 'pool': - # http://deb.debian.org/debian/pool/main/a/adduser/adduser_3.134_all.deb - return '/'.join(uri_parts[:-5]) - elif uri_parts[-6] == 'pool': - # http://deb.debian.org/debian-security/pool/updates/main/u/util-linux/bsdutils_2.38.1-5%2bdeb12u1_amd64.deb - return '/'.join(uri_parts[:-6]) - else: - raise ValueError('URI needs to be in pool layout') + parsed = urllib.parse.urlsplit(uri) + path_parts = parsed.path.split('/') + + if path_parts[-1].endswith('.deb'): + # Standard Debian layout: repository root is everything before /pool/. + if 'pool' in path_parts: + repo_path = '/'.join(path_parts[:path_parts.index('pool')]) + else: + # Flat repository: repo URL is everything before the filename. + repo_path = '/'.join(path_parts[:-1]) + + if not repo_path: + repo_path = '/' + + return urllib.parse.urlunsplit((parsed.scheme, parsed.netloc, repo_path, '', '')) + + raise ValueError(f'Unexpected URI format: {uri}') def _purl_from_pkg(pkg): diff --git a/elbepack/tests/cyclonedx/test_cyclonedx_sbom.py b/elbepack/tests/cyclonedx/test_cyclonedx_sbom.py index 79981678f..228a44114 100644 --- a/elbepack/tests/cyclonedx/test_cyclonedx_sbom.py +++ b/elbepack/tests/cyclonedx/test_cyclonedx_sbom.py @@ -94,6 +94,10 @@ def test_reference_data(): 'bsdutils_2.38.1-5%2bdeb12u1_amd64.deb', 'http://deb.debian.org/debian-security', ), + ( + 'https://deb.corporate.com/corp/foo/ethtool_6.14.2-1%7edeb13u1_arm64.deb', + 'https://deb.corporate.com/corp/foo', + ), ]) def test_repository_url_examples(uri, expected_repository_url): cyclonedx_sbom = import_cmd_module('cyclonedx-sbom') diff --git a/newsfragments/+scyclonedx-sbom-flat-repos.rst b/newsfragments/+scyclonedx-sbom-flat-repos.rst new file mode 100644 index 000000000..58252eab6 --- /dev/null +++ b/newsfragments/+scyclonedx-sbom-flat-repos.rst @@ -0,0 +1 @@ +Extend cyclonedx-sbom command to support flat repositories (e.g. minidinst).