public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/package-notes] f44: Version 0.17
@ 2026-06-02 16:28 
  0 siblings, 0 replies; only message in thread
From:  @ 2026-06-02 16:28 UTC (permalink / raw)
  To: git-commits

            A new commit has been pushed.

            Repo   : rpms/package-notes
            Branch : f44
            Commit : 9909a5098bbe9e4e017fa7c50b2309ff47905934
            Author : Zbigniew Jędrzejewski-Szmek <zbyszek@amutable.com>
            Date   : 2026-02-06T12:07:17+01:00
            Stats  : +416/-22 in 7 file(s)
            URL    : https://src.fedoraproject.org/rpms/package-notes/c/9909a5098bbe9e4e017fa7c50b2309ff47905934?branch=f44

            Log:
            Version 0.17

- This is a major version upgrade that allows automatic generation of
  Requires/Recommends/Suggests from package dlopen notes. See the new
  macro file for details of use.
- The new fileattr plugin is in the package-notes subpackage, so that
  needs to be installed to activate the feature.

---
diff --git a/0001-Fix-type-in-group_by_feature.patch b/0001-Fix-type-in-group_by_feature.patch
new file mode 100644
index 0000000..5721460
--- /dev/null
+++ b/0001-Fix-type-in-group_by_feature.patch
@@ -0,0 +1,23 @@
+From a2f9622f3f21b80b3cfbf9ce76fbc2dc721ecf13 Mon Sep 17 00:00:00 2001
+From: Arthur Petitpierre <bartaba@smallstone.org>
+Date: Wed, 7 Jan 2026 17:48:14 +0700
+Subject: [PATCH 1/6] Fix type in group_by_feature
+
+In group_by_feature, fix typo "recommened" -> "recommended".
+---
+ dlopen-notes.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/dlopen-notes.py b/dlopen-notes.py
+index 3d5b651fd9..e55800c98d 100755
+--- a/dlopen-notes.py
++++ b/dlopen-notes.py
+@@ -98,7 +98,7 @@ def group_by_feature(elffiles):
+     # ]
+     for elffiles in elffiles:
+         for note in elffiles.notes():
+-            prio = Priority[note.get('priority', 'recommened')]
++            prio = Priority[note.get('priority', 'recommended')]
+             feature_name = note['feature']
+ 
+             try:

diff --git a/0001-rpm-use-a-r-.-guard-around-package-notes-LDFLAGS.patch b/0001-rpm-use-a-r-.-guard-around-package-notes-LDFLAGS.patch
deleted file mode 100644
index 6fca390..0000000
--- a/0001-rpm-use-a-r-.-guard-around-package-notes-LDFLAGS.patch
+++ /dev/null
@@ -1,19 +0,0 @@
-From e52dfeba8ba36fc765fbe0ff0d4c93ed9aac493b Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20B=C3=A9rat?= <fberat@redhat.com>
-Date: Tue, 27 Jan 2026 11:31:16 +0100
-Subject: [PATCH] rpm: use a '%{!r: ... }' guard around package notes LDFLAGS
-
-...to prevent double inclusion when performing a relocatable link ('-r').
-Relates to https://bugzilla.redhat.com/show_bug.cgi?id=2362272.
----
- rpm/redhat-package-notes.in | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/rpm/redhat-package-notes.in b/rpm/redhat-package-notes.in
-index 3a19b1be8a..1297ae5261 100644
---- a/rpm/redhat-package-notes.in
-+++ b/rpm/redhat-package-notes.in
-@@ -1,2 +1,2 @@
- *link:
--+ --package-metadata={\"type\":\"rpm\",\"name\":\"%:getenv(RPM_PACKAGE_NAME \",\"version\":\"%:getenv(RPM_PACKAGE_VERSION -%:getenv(RPM_PACKAGE_RELEASE \",\"architecture\":\"%:getenv(RPM_ARCH \",\"osCpe\":\"@OSCPE@\"}))))
-++ %{!r:--package-metadata={\"type\":\"rpm\",\"name\":\"%:getenv(RPM_PACKAGE_NAME \",\"version\":\"%:getenv(RPM_PACKAGE_VERSION -%:getenv(RPM_PACKAGE_RELEASE \",\"architecture\":\"%:getenv(RPM_ARCH \",\"osCpe\":\"@OSCPE@\"}))))}

diff --git a/0002-dlopen-notes-group-two-helper-functions-together.patch b/0002-dlopen-notes-group-two-helper-functions-together.patch
new file mode 100644
index 0000000..99f7bef
--- /dev/null
+++ b/0002-dlopen-notes-group-two-helper-functions-together.patch
@@ -0,0 +1,37 @@
+From 2ad3aca11e60a9f50574a65df2232dfb58597f2b Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Mon, 12 Jan 2026 13:57:06 +0100
+Subject: [PATCH 2/6] dlopen-notes: group two helper functions together
+
+---
+ dlopen-notes.py | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/dlopen-notes.py b/dlopen-notes.py
+index e55800c98d..f103611c00 100755
+--- a/dlopen-notes.py
++++ b/dlopen-notes.py
+@@ -19,6 +19,11 @@ try:
+ except ImportError:
+     print_json = print
+ 
++def dictify(f):
++    def wrap(*args, **kwargs):
++        return dict(f(*args, **kwargs))
++    return functools.update_wrapper(wrap, f)
++
+ def listify(f):
+     def wrap(*args, **kwargs):
+         return list(f(*args, **kwargs))
+@@ -63,11 +68,6 @@ class ELFFileReader:
+ 
+                 yield from j
+ 
+-def dictify(f):
+-    def wrap(*args, **kwargs):
+-        return dict(f(*args, **kwargs))
+-    return functools.update_wrapper(wrap, f)
+-
+ @dictify
+ def group_by_soname(elffiles):
+     for elffile in elffiles:

diff --git a/0003-rpm-add-fileattr-multifile-generator.patch b/0003-rpm-add-fileattr-multifile-generator.patch
new file mode 100644
index 0000000..23ddbd1
--- /dev/null
+++ b/0003-rpm-add-fileattr-multifile-generator.patch
@@ -0,0 +1,270 @@
+From d6e833810909a4278f59c19dbc748424ca5e153f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Tue, 13 Jan 2026 14:14:22 +0100
+Subject: [PATCH 3/6] rpm: add fileattr multifile generator
+
+This allows dlopen notes to be turned into appropriate dependencies
+automatically. The dlopen_notes.attr file needs to be installed into
+%{_fileattrsdir}.
+
+By default, dependencies are generated for all files that have package
+notes. I think this is a reasonable default because it makes the whole
+feature easier to discover. In more realistic cases, esp. with
+multiple subpackages, it's likely that the packager may need to
+configure the distribution of dependencies between subpackages.
+
+One shortcoming of the scheme is that everything is per file, so it's
+not possible to say that dependencies generated from a feature should
+be assigned to a different subpackage. This is how the feature is
+designed in rpm.
+
+The opt-out mechanism is a bit clunky. The first option I considered
+was to tell the user to undefine
+%__dlopen_notes_requires/recommends/suggests, but that requires three
+lines of boilerplate. And might not be forwards-compatible if we add
+new features in the future. The second option would be to tell the
+user to define __dlopen_notes_requires/recommends/suggests_opts to
+%nil. But that has similar problems. I think it's nice to have an
+obvious oneliner to handle this. Unfortunately, when I tried to use
+  %__dlopen_notes_requires %{?_dlopen_notes_generator:%{_dlopen_notes_generator} ...}
+  %__dlopen_notes_recommends %{?_dlopen_notes_generator:%{_dlopen_notes_generator} ...}
+  %__dlopen_notes_suggests %{?_dlopen_notes_generator:%{_dlopen_notes_generator} ...}
+in the .attr file, when the package has %undefine _dlopen_notes_generator,
+we still end up with the macro being expanded. Maybe I misunderstood
+the macro expansion logic. The approach with 'true' is clunky, but
+it works fine.
+
+Thanks to Neal Gompa for the suggestion to use this protocol.
+
+The new interface is new, independent of the existing options
+--feature, --rpm-recommends, --rpm-requires that were previously added
+to support rpms. Unfortunately, with the fileattr protocol, the
+old way to specify information is not useful. Instead of trying
+to shoehorn the new metadata into existing options, I think it's
+easier to add a new set with clear semantics.
+---
+ README.md             | 13 ++++++
+ dlopen-notes.py       | 96 +++++++++++++++++++++++++++++++++++++++++--
+ rpm/dlopen_notes.attr | 44 ++++++++++++++++++++
+ 3 files changed, 150 insertions(+), 3 deletions(-)
+ create mode 100644 rpm/dlopen_notes.attr
+
+diff --git a/README.md b/README.md
+index 8b27e19de3..f7fa518630 100644
+--- a/README.md
++++ b/README.md
+@@ -97,6 +97,19 @@ $ dlopen-notes /usr/lib64/systemd/libsystemd-shared-257.so
+ ...
+ ```
+ 
++### Using the rpm fileattr generator
++
++The tool that processes package notes can be hooked into the rpm build process
++to automatically generate virtual `Requires`, `Recommends`, and `Suggests` dependencies.
++
++The rpm file attribute mechanism is described in
++[rpm-dependency-generators.7](https://rpm-software-management.github.io/rpm/man/rpm-dependency-generators.7).
++
++This tool implements the 'multifile' protocol:
++it reads the list of files on stdin and outputs a list of virtual dependencies.
++
++See the `rpm/dlopen_notes.attr` file for invocation details and options.
++
+ ## Requirements
+ * binutils (>= 2.39)
+ * mold (>= 1.3.0)
+diff --git a/dlopen-notes.py b/dlopen-notes.py
+index f103611c00..4fa30d8e89 100755
+--- a/dlopen-notes.py
++++ b/dlopen-notes.py
+@@ -7,6 +7,7 @@ Read .note.dlopen notes from ELF files and report the contents.
+ 
+ import argparse
+ import enum
++import fnmatch
+ import functools
+ import json
+ import sys
+@@ -84,6 +85,16 @@ class Priority(enum.Enum):
+     def __lt__(self, other):
+         return self.value < other.value
+ 
++    def rpm_name(self):
++        if self == self.__class__.suggested:
++            return 'Suggests'
++        if self == self.__class__.recommended:
++            return 'Recommends'
++        if self == self.__class__.required:
++            return 'Requires'
++        raise ValueError
++
++
+ def group_by_feature(elffiles):
+     features = {}
+ 
+@@ -143,6 +154,52 @@ def generate_rpm(elffiles, stanza, filter):
+                 soname = next(iter(note['soname']))  # we take the first — most recommended — soname
+                 yield f"{stanza}: {soname}{suffix}"
+ 
++def rpm_fileattr_generator(args):
++    if args.rpm_features is not None:
++        if not any(fnmatch.fnmatch(args.subpackage, pattern[0])
++                   for pattern in args.rpm_features):
++            # Current subpackage is not listed, nothing to do.
++            # Consume all input as required by the protocol.
++            sys.stdin.read()
++            return
++
++    for file in sys.stdin:
++        file = file.strip()
++        if not file:
++            continue  # ignore empty lines
++
++        elffile = ELFFileReader(file)
++        suffix = '()(64bit)' if elffile.elffile.elfclass == 64 else ''
++
++        first = True
++
++        for note in elffile.notes():
++            # Feature name is optional. Allow this to be matched
++            # by the empty string ('') or a wildcard glob ('*').
++            feature = note.get('feature', '')
++
++            if args.rpm_features is not None:
++                for package_pattern,feature_pattern in args.rpm_features:
++                    if (fnmatch.fnmatch(args.subpackage, package_pattern) and
++                        fnmatch.fnmatch(feature, feature_pattern)):
++                        break
++                else:
++                    # not matched
++                    continue
++            else:
++                # if no mapping, print all features at the suggested level
++                level = Priority[note.get('priority', 'recommended')].rpm_name()
++                if level != args.rpm_fileattr:
++                    continue
++
++            if first:
++                print(f';{file}')
++                first = False
++
++            soname = next(iter(note['soname']))  # we take the first — most recommended — soname
++            print(f'{soname}{suffix}')
++
++
+ def make_parser():
+     p = argparse.ArgumentParser(
+         description=__doc__,
+@@ -187,10 +244,28 @@ def make_parser():
+         metavar='FEATURE1,FEATURE2',
+         help='Generate rpm Recommends for listed features',
+     )
++    p.add_argument(
++        '--rpm-fileattr',
++        metavar='TYPE',
++        help='Run as rpm fileattr generator for TYPE dependencies',
++    )
++    p.add_argument(
++        '--subpackage',
++        metavar='NAME',
++        default='',
++        help='Current subpackage NAME',
++    )
++    p.add_argument(
++        '--rpm-features',
++        metavar='SUBPACKAGE:FEATURE,SUBPACKAGE:FEATURE',
++        type=lambda s: [x.split(':', maxsplit=1) for x in s.split(',')],
++        action='extend',
++        help='Specify subpackage:feature mapping',
++    )
+     p.add_argument(
+         'filenames',
+-        nargs='+',
+-        metavar='filename',
++        nargs='*',
++        metavar='FILENAME',
+         help='Library file to extract notes from',
+     )
+     p.add_argument(
+@@ -207,15 +282,30 @@ def parse_args():
+         and not args.sonames
+         and args.features is None
+         and args.rpm_requires is None
+-        and args.rpm_recommends is None):
++        and args.rpm_recommends is None
++        and args.rpm_fileattr is None):
+         # Make --raw the default if no action is specified.
+         args.raw = True
+ 
++    if args.rpm_fileattr is not None:
++        if (args.filenames
++            or args.raw
++            or args.features is not None
++            or args.rpm_requires
++            or args.rpm_recommends):
++            raise ValueError('--rpm-generate cannot be combined with most options')
++
++    if args.rpm_fileattr is None and not args.filenames:
++        raise ValueError('At least one positional FILENAME parameter is required')
++
+     return args
+ 
+ if __name__ == '__main__':
+     args = parse_args()
+ 
++    if args.rpm_fileattr is not None:
++        sys.exit(rpm_fileattr_generator(args))
++
+     elffiles = [ELFFileReader(filename) for filename in args.filenames]
+     features = group_by_feature(elffiles)
+ 
+diff --git a/rpm/dlopen_notes.attr b/rpm/dlopen_notes.attr
+new file mode 100644
+index 0000000000..abe3e8547c
+--- /dev/null
++++ b/rpm/dlopen_notes.attr
+@@ -0,0 +1,44 @@
++# SPDX-License-Identifier: MIT-0
++#
++# This file is part of the package-notes package.
++#
++#
++# The spec file for a package can specify which features are listed
++# and at which level, using
++# '--rpm-features=SUBPACKAGE1:FEATURE1,SUBPACKAGE2:FEATURE2' option in
++# the '__dlopen_notes_TYPE_opts' macro, where TYPE is one of
++# 'requires', 'recommends', or 'suggests'. The macro should be declared
++# in the spec file using:
++#   %define __dlopen_notes_TYPE_opts SUBPACKAGE:FEATURE…
++# e.g.
++#   %define __dlopen_notes_recommends_opts *:zstd
++#
++# The option accepts multiple comma-separated pairs, and can also be
++# specified multiple times. Both the subpackage name and feature name
++# can be a glob. If configuration is omitted, the priority recommended
++# in the notes is used.
++#
++# The '--subpackage=SUBPACKAGE' option (inserted below) tells the generator
++# which subpackage is being processed.
++#
++# For example, for a package using compression libraries, we can say
++# that the 'package-libs' subpackage shall carry 'Requires' on all the
++# libraries needed for the 'zstd' feature, all subpackages shall carry
++# 'Recommends' on all the libraries needed for the 'gzip' feature, and
++# the 'package' subpackage shall carry 'Suggests' for any feature
++# matching 'lzma' or 'bzip*'.
++#
++#  %define __dlopen_notes_requires_opts   --rpm-features=package-libs:zstd
++#  %define __dlopen_notes_recommends_opts --rpm-features=*:gzip
++#  %define __dlopen_notes_suggests_opts   --rpm-features=package:lzma,package:bzip*
++#
++# To opt out, undefine the %_dlopen_notes_generator macro:
++#  %undefine _dlopen_notes_generator
++
++%_dlopen_notes_generator   %{_bindir}/dlopen-notes
++
++%__dlopen_notes_requires   %{!?_dlopen_notes_generator:true }%{_dlopen_notes_generator} --subpackage='%{name}' --rpm-fileattr=Requires
++%__dlopen_notes_recommends %{!?_dlopen_notes_generator:true }%{_dlopen_notes_generator} --subpackage='%{name}' --rpm-fileattr=Recommends
++%__dlopen_notes_suggests   %{!?_dlopen_notes_generator:true }%{_dlopen_notes_generator} --subpackage='%{name}' --rpm-fileattr=Suggests
++%__dlopen_notes_protocol   multifile
++%__dlopen_notes_magic      ^.*ELF (32|64)-bit.*$

diff --git a/0004-fakelib-add-test-for-the-new-fileattr-plugin.patch b/0004-fakelib-add-test-for-the-new-fileattr-plugin.patch
new file mode 100644
index 0000000..8b19a33
--- /dev/null
+++ b/0004-fakelib-add-test-for-the-new-fileattr-plugin.patch
@@ -0,0 +1,57 @@
+From 9f6142b43b730d2ff51cf2b355050548f5f8fc9e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Tue, 13 Jan 2026 09:53:07 +0100
+Subject: [PATCH 4/6] fakelib: add test for the new fileattr plugin
+
+This is a package that "builds" by copying two files: a systemd
+library that is known to use dlopen notes and another glibc library
+that doesn't have them. It can be built with 'rpmbuild' or 'fedpkg local'.
+For example:
+  (cd fakelib && fedpkg local && echo 'Requires:' && rpm -qpv --requires x86_64/fakelib-0-1.fc44.x86_64.rpm && echo 'Recommends:' && rpm -qpv --recommends x86_64/fakelib-0-1.fc44.x86_64.rpm && echo 'Suggests:' && rpm -qpv --suggests x86_64/fakelib-0-1.fc44.x86_64.rpm)
+---
+ fakelib/fakelib.spec | 36 ++++++++++++++++++++++++++++++++++++
+ 1 file changed, 36 insertions(+)
+ create mode 100644 fakelib/fakelib.spec
+
+diff --git a/fakelib/fakelib.spec b/fakelib/fakelib.spec
+new file mode 100644
+index 0000000000..40714cbeb1
+--- /dev/null
++++ b/fakelib/fakelib.spec
+@@ -0,0 +1,36 @@
++# SPDX-License-Identifier: MIT-0
++#
++# This file is part of the package-notes package.
++
++Name:           fakelib
++Version:        0
++Release:        %autorelease
++Summary:        %{name}
++
++License:        None
++
++%define __dlopen_notes_requires_opts   --rpm-features=fakelib:gcrypt,fakelib:lz4
++%define __dlopen_notes_recommends_opts --rpm-features=*:zstd
++%define __dlopen_notes_suggests_opts   --rpm-features=fakelib:lzm[abc]
++
++#undefine _dlopen_notes_generator
++
++%description
++%{summary}.
++
++%prep
++
++%build
++
++%install
++install -Dt %{buildroot}/usr/lib64/ /usr/lib64/libsystemd.so.0
++ln -s libsystemd.so.0 %{buildroot}/usr/lib64/libsystemd.so
++install -Dt %{buildroot}/usr/lib64/ /usr/lib64/libmvec.so.1
++
++%files
++/usr/lib64/libsystemd.so.0
++/usr/lib64/libsystemd.so
++/usr/lib64/libmvec.so.1
++
++%changelog
++%autochangelog

diff --git a/0005-rpm-use-a-r-.-guard-around-package-notes-LDFLAGS.patch b/0005-rpm-use-a-r-.-guard-around-package-notes-LDFLAGS.patch
new file mode 100644
index 0000000..be26cf0
--- /dev/null
+++ b/0005-rpm-use-a-r-.-guard-around-package-notes-LDFLAGS.patch
@@ -0,0 +1,20 @@
+From e52dfeba8ba36fc765fbe0ff0d4c93ed9aac493b Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20B=C3=A9rat?= <fberat@redhat.com>
+Date: Tue, 27 Jan 2026 11:31:16 +0100
+Subject: [PATCH 5/6] rpm: use a '%{!r: ... }' guard around package notes
+ LDFLAGS
+
+...to prevent double inclusion when performing a relocatable link ('-r').
+Relates to https://bugzilla.redhat.com/show_bug.cgi?id=2362272.
+---
+ rpm/redhat-package-notes.in | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/rpm/redhat-package-notes.in b/rpm/redhat-package-notes.in
+index 3a19b1be8a..1297ae5261 100644
+--- a/rpm/redhat-package-notes.in
++++ b/rpm/redhat-package-notes.in
+@@ -1,2 +1,2 @@
+ *link:
+-+ --package-metadata={\"type\":\"rpm\",\"name\":\"%:getenv(RPM_PACKAGE_NAME \",\"version\":\"%:getenv(RPM_PACKAGE_VERSION -%:getenv(RPM_PACKAGE_RELEASE \",\"architecture\":\"%:getenv(RPM_ARCH \",\"osCpe\":\"@OSCPE@\"}))))
+++ %{!r:--package-metadata={\"type\":\"rpm\",\"name\":\"%:getenv(RPM_PACKAGE_NAME \",\"version\":\"%:getenv(RPM_PACKAGE_VERSION -%:getenv(RPM_PACKAGE_RELEASE \",\"architecture\":\"%:getenv(RPM_ARCH \",\"osCpe\":\"@OSCPE@\"}))))}

diff --git a/package-notes.spec b/package-notes.spec
index 5a549ce..c040d89 100644
--- a/package-notes.spec
+++ b/package-notes.spec
@@ -1,5 +1,5 @@
 Name:           package-notes
-Version:        0.16
+Version:        0.17
 Release:        %autorelease
 Summary:        ELF Package and Dlopen Notes
 License:        0BSD
@@ -9,7 +9,11 @@ Source:         https://github.com/systemd/package-notes/archive/v%{version_no_t
 BuildArch:      noarch
 Requires:       python3dist(pyelftools)
 
-Patch:          0001-rpm-use-a-r-.-guard-around-package-notes-LDFLAGS.patch
+Patch:          0001-Fix-type-in-group_by_feature.patch
+Patch:          0002-dlopen-notes-group-two-helper-functions-together.patch
+Patch:          0003-rpm-add-fileattr-multifile-generator.patch
+Patch:          0004-fakelib-add-test-for-the-new-fileattr-plugin.patch
+Patch:          0005-rpm-use-a-r-.-guard-around-package-notes-LDFLAGS.patch
 
 %description
 This package provides rpm macros to generate an '.note.package' ELF note in
@@ -25,6 +29,7 @@ See https://systemd.io/ELF_DLOPEN_METADATA/ for the overview and details.
 
 %files
 %{_bindir}/dlopen-notes
+%{_fileattrsdir}/dlopen_notes.attr
 %{_mandir}/man1/dlopen-notes.1*
 
 %package srpm-macros
@@ -54,7 +59,8 @@ sed "s|@OSCPE@|$(cat /usr/lib/system-release-cpe)|" rpm/redhat-package-notes.in 
 %make_install
 
 install -Dt %{buildroot}%{_rpmconfigdir}/redhat/ rpm/redhat-package-notes
-install -m0644 -Dt %{buildroot}%{_rpmmacrodir}/ rpm/macros.package-notes-srpm
+install -m0644 -Dt %{buildroot}%{_rpmmacrodir}/  rpm/macros.package-notes-srpm
+install -m0644 -Dt %{buildroot}%{_fileattrsdir}/ rpm/dlopen_notes.attr
 
 %changelog
 %autochangelog

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-06-02 16:28 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-02 16:28 [rpms/package-notes] f44: Version 0.17 

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox