public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/rpkg] 1.70-1: A few patches:
@ 2026-08-10 21:44 
  0 siblings, 0 replies; 6+ messages in thread
From:  @ 2026-08-10 21:44 UTC (permalink / raw)
  To: git-commits

            A new commit has been pushed.

            Repo   : rpms/rpkg
            Branch : 1.70-1
            Commit : b48b2893740995636fe9e2496130e5bb5f4ab749
            Author : Ondřej Nosek <onosek@redhat.com>
            Date   : 2024-01-10T03:03:43+00:00
            Stats  : +1560/-1197 in 25 file(s)
            URL    : https://src.fedoraproject.org/rpms/rpkg/c/b48b2893740995636fe9e2496130e5bb5f4ab749?branch=1.70-1

            Log:
            A few patches:

- Patch: Add option to mockbuild use default resultdir of mock (v3)
- Patch: mockbuild`: new argument --extra-pkgs
- Patch: `copr-build` passes extra_args to copr-cli command

Signed-off-by: Ondřej Nosek <onosek@redhat.com>

---
diff --git a/0022-commit-command-fails-on-containers-namespace.patch b/0022-commit-command-fails-on-containers-namespace.patch
deleted file mode 100644
index a284abc..0000000
--- a/0022-commit-command-fails-on-containers-namespace.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From 7ade8c1f38efaa8817bd10df6b0928ef70822f6e Mon Sep 17 00:00:00 2001
-From: Ondrej Nosek <onosek@redhat.com>
-Date: Wed, 17 May 2023 00:32:47 +0200
-Subject: [PATCH] `commit` command fails on 'containers' namespace
-
-Commit failed when 'uses_rpmautospec' tried to search for a specfile.
-There is no specfile in 'containers' namespace repository.
-
-JIRA: RHELCMP-11734
-
-Signed-off-by: Ondrej Nosek <onosek@redhat.com>
----
- pyrpkg/__init__.py | 11 +++++++++--
- 1 file changed, 9 insertions(+), 2 deletions(-)
-
-diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py
-index f14b055..b45ad8f 100644
---- a/pyrpkg/__init__.py
-+++ b/pyrpkg/__init__.py
-@@ -1872,8 +1872,15 @@ class Commands(object):
-         # construct the git command
-         # We do this via subprocess because the git module is terrible.
-         cmd = ['git', 'commit']
--        if not self.is_retired() and self.uses_rpmautospec:
--            cmd.append('--allow-empty')
-+        if not self.is_retired():
-+            try:
-+                # raises exception when a specfile is missing
-+                # (for example when processing "containers" namespace repository)
-+                uses_rpmautospec = self.uses_rpmautospec
-+            except Exception:
-+                uses_rpmautospec = False
-+            if uses_rpmautospec:
-+                cmd.append('--allow-empty')
-         if signoff:
-             cmd.append('-s')
-         if self.quiet:
--- 
-2.40.1
-

diff --git a/0022-copr-build-passes-extra_args-to-copr-cli-command.patch b/0022-copr-build-passes-extra_args-to-copr-cli-command.patch
new file mode 100644
index 0000000..966f0ef
--- /dev/null
+++ b/0022-copr-build-passes-extra_args-to-copr-cli-command.patch
@@ -0,0 +1,113 @@
+From ad67fa9069befef3e4ba5180eea6bf56b658e664 Mon Sep 17 00:00:00 2001
+From: Ondrej Nosek <onosek@redhat.com>
+Date: Wed, 3 May 2023 00:41:34 +0200
+Subject: [PATCH 01/17] `copr-build` passes extra_args to copr-cli command
+
+The right target for passing extra_args (arguments that are placed
+after '--' on the command line) is the command copr-cli instead
+of rpmbuild command.
+
+Fixes: https://pagure.io/fedpkg/issue/510
+JIRA: RHELCMP-11429
+
+Signed-off-by: Ondrej Nosek <onosek@redhat.com>
+---
+ pyrpkg/__init__.py |  5 ++++-
+ pyrpkg/cli.py      | 11 ++++++++++-
+ tests/test_cli.py  | 24 ++++++++++++++++++++++++
+ 3 files changed, 38 insertions(+), 2 deletions(-)
+
+diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py
+index 11b8dae..f14b055 100644
+--- a/pyrpkg/__init__.py
++++ b/pyrpkg/__init__.py
+@@ -3576,13 +3576,16 @@ class Commands(object):
+         else:
+             self.log.info('Nothing to be done')
+ 
+-    def copr_build(self, project, srpm_name, nowait, config_file):
++    def copr_build(self, project, srpm_name, nowait, config_file, extra_args=None):
+         cmd = ['copr-cli']
+         if config_file:
+             cmd.extend(['--config', config_file])
+         cmd.append('build')
+         if nowait:
+             cmd.append('--nowait')
++        if extra_args:
++            cmd.extend(extra_args)
++            self.log.debug("Extra args '{0}' are passed to copr-cli command".format(extra_args))
+         cmd.extend([project, srpm_name])
+         self._run_command(cmd)
+ 
+diff --git a/pyrpkg/cli.py b/pyrpkg/cli.py
+index dc1eb4e..020a247 100644
+--- a/pyrpkg/cli.py
++++ b/pyrpkg/cli.py
+@@ -1561,6 +1561,10 @@ class cliClient(object):
+             help="Don't wait on build")
+         copr_parser.add_argument(
+             'project', nargs=1, help='Name of the project in format USER/PROJECT')
++        copr_parser.add_argument(
++            "extra_args", default=None, nargs=argparse.REMAINDER,
++            help="Custom arguments that are passed to the 'copr-cli'. "
++                 "Use '--' to separate them from other arguments.")
+         copr_parser.set_defaults(command=self.copr_build)
+ 
+     def register_switch_branch(self):
+@@ -2354,12 +2358,17 @@ class cliClient(object):
+     def copr_build(self):
+         self.log.debug('Generating an srpm')
+         self.args.hash = None
++        # do not pass 'extra_args' to 'rpmbuild' command in 'srpm' method; Pass it to copr-cli.
++        extra_args_backup = self.extra_args
++        self.extra_args = None
+         self.srpm()
++        self.extra_args = extra_args_backup
+         srpm_name = '%s.src.rpm' % self.cmd.nvr
+         self.cmd.copr_build(self.args.project[0],
+                             srpm_name,
+                             self.args.nowait,
+-                            self.args.copr_config)
++                            self.args.copr_config,
++                            extra_args=self.extra_args)
+ 
+     def diff(self):
+         self.cmd.diff(self.args.cached, self.args.files)
+diff --git a/tests/test_cli.py b/tests/test_cli.py
+index 6e4ec6a..f2e68df 100644
+--- a/tests/test_cli.py
++++ b/tests/test_cli.py
+@@ -636,6 +636,30 @@ class TestClone(CliTestCase):
+         output = sys.stderr.getvalue().strip()
+         self.assertEqual('', output)
+ 
++    @patch('sys.stderr', new=StringIO())
++    @patch('pyrpkg.Commands._clone_config', new_callable=Mock())
++    @patch('pyrpkg.Commands._run_command')
++    def test_extra_args_copr(self, _run_command, _clone_config):
++        # copr-build is the command that has two subcommands (rpmbuild and copr-cli)
++        # that might accept the extra args. This tests requies extra_args at copr-cli.
++        cli_cmd = ['rpkg', '--user', 'dude', '--path', self.cloned_repo_path,
++                   '--release', 'rhel-6', 'copr-build', 'COPR-REPO',
++                   '--', '--after-build-id', 'ID']
++
++        with patch('sys.argv', new=cli_cmd):
++            cli = self.new_cli()
++            cli.copr_build()
++
++        expected_cmd = ['copr-cli', 'build', '--after-build-id', 'ID', 'COPR-REPO']
++        self.assertEqual(2, _run_command.call_count)
++        copr_cli_call = _run_command.mock_calls[1]
++        if 'args' in dir(copr_cli_call):  # doesn't work in <=py36
++            # strip the last argument - it contains dynamically generated src.rpm filename
++            self.assertEqual(expected_cmd, copr_cli_call.args[0][:-1])
++
++        output = sys.stderr.getvalue().strip()
++        self.assertEqual('', output)
++
+     @patch('sys.stderr', new=StringIO())
+     @patch('pyrpkg.Commands._clone_config', new_callable=Mock())
+     @patch('pyrpkg.Commands._run_command')
+-- 
+2.43.0
+

diff --git a/0023-Split-git-credential-data-on-first-only.patch b/0023-Split-git-credential-data-on-first-only.patch
deleted file mode 100644
index 43416b7..0000000
--- a/0023-Split-git-credential-data-on-first-only.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-From 75d42bad79b54654fca9770a2857e79e82d83c3e Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Lubom=C3=ADr=20Sedl=C3=A1=C5=99?= <lsedlar@redhat.com>
-Date: Wed, 21 Jun 2023 10:42:45 +0200
-Subject: [PATCH 1/3] Split git credential data on first = only
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-The value itself can contain a = character, but we don't really care
-about that. We can treat the value of the key as opaque.
-
-Fixes: https://pagure.io/rpkg/issue/694
-Signed-off-by: Lubomír Sedlář <lsedlar@redhat.com>
----
- pyrpkg/cli.py | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/pyrpkg/cli.py b/pyrpkg/cli.py
-index 020a247..1bd7979 100644
---- a/pyrpkg/cli.py
-+++ b/pyrpkg/cli.py
-@@ -824,7 +824,7 @@ class cliClient(object):
-         """Parses the git-credential-helper IO format input."""
-         inp = {}
-         for line in sys.stdin:
--            vals = line.split('=', 2)
-+            vals = line.split('=', 1)
-             if len(vals) != 2:
-                 print('Invalid input: %s' % line, file=sys.stderr)
-                 return False
--- 
-2.41.0
-

diff --git a/0023-commit-command-fails-on-containers-namespace.patch b/0023-commit-command-fails-on-containers-namespace.patch
new file mode 100644
index 0000000..21ae8e3
--- /dev/null
+++ b/0023-commit-command-fails-on-containers-namespace.patch
@@ -0,0 +1,40 @@
+From 7ade8c1f38efaa8817bd10df6b0928ef70822f6e Mon Sep 17 00:00:00 2001
+From: Ondrej Nosek <onosek@redhat.com>
+Date: Wed, 17 May 2023 00:32:47 +0200
+Subject: [PATCH 02/17] `commit` command fails on 'containers' namespace
+
+Commit failed when 'uses_rpmautospec' tried to search for a specfile.
+There is no specfile in 'containers' namespace repository.
+
+JIRA: RHELCMP-11734
+
+Signed-off-by: Ondrej Nosek <onosek@redhat.com>
+---
+ pyrpkg/__init__.py | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py
+index f14b055..b45ad8f 100644
+--- a/pyrpkg/__init__.py
++++ b/pyrpkg/__init__.py
+@@ -1872,8 +1872,15 @@ class Commands(object):
+         # construct the git command
+         # We do this via subprocess because the git module is terrible.
+         cmd = ['git', 'commit']
+-        if not self.is_retired() and self.uses_rpmautospec:
+-            cmd.append('--allow-empty')
++        if not self.is_retired():
++            try:
++                # raises exception when a specfile is missing
++                # (for example when processing "containers" namespace repository)
++                uses_rpmautospec = self.uses_rpmautospec
++            except Exception:
++                uses_rpmautospec = False
++            if uses_rpmautospec:
++                cmd.append('--allow-empty')
+         if signoff:
+             cmd.append('-s')
+         if self.quiet:
+-- 
+2.43.0
+

diff --git a/0024-Split-git-credential-data-on-first-only.patch b/0024-Split-git-credential-data-on-first-only.patch
new file mode 100644
index 0000000..8f7ab6b
--- /dev/null
+++ b/0024-Split-git-credential-data-on-first-only.patch
@@ -0,0 +1,33 @@
+From 75d42bad79b54654fca9770a2857e79e82d83c3e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Lubom=C3=ADr=20Sedl=C3=A1=C5=99?= <lsedlar@redhat.com>
+Date: Wed, 21 Jun 2023 10:42:45 +0200
+Subject: [PATCH 03/17] Split git credential data on first = only
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The value itself can contain a = character, but we don't really care
+about that. We can treat the value of the key as opaque.
+
+Fixes: https://pagure.io/rpkg/issue/694
+Signed-off-by: Lubomír Sedlář <lsedlar@redhat.com>
+---
+ pyrpkg/cli.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/pyrpkg/cli.py b/pyrpkg/cli.py
+index 020a247..1bd7979 100644
+--- a/pyrpkg/cli.py
++++ b/pyrpkg/cli.py
+@@ -824,7 +824,7 @@ class cliClient(object):
+         """Parses the git-credential-helper IO format input."""
+         inp = {}
+         for line in sys.stdin:
+-            vals = line.split('=', 2)
++            vals = line.split('=', 1)
+             if len(vals) != 2:
+                 print('Invalid input: %s' % line, file=sys.stderr)
+                 return False
+-- 
+2.43.0
+

diff --git a/0024-Support-for-checking-exploded-sources-before-push.patch b/0024-Support-for-checking-exploded-sources-before-push.patch
deleted file mode 100644
index e8f14de..0000000
--- a/0024-Support-for-checking-exploded-sources-before-push.patch
+++ /dev/null
@@ -1,71 +0,0 @@
-From 87d4995b40fbcddac88fb21191eb2d5d1f248550 Mon Sep 17 00:00:00 2001
-From: Ondrej Nosek <onosek@redhat.com>
-Date: Tue, 11 Jul 2023 17:00:48 +0200
-Subject: [PATCH 2/3] Support for checking exploded sources before push
-
-pre-push-check now includes test whether source files listed
-in a specfile come from additional sources.
-This functionality is relevant only for some x-pkg tools, others
-should not be affected.
-
-JIRA: RHELCMP-11777
-
-Signed-off-by: Ondrej Nosek <onosek@redhat.com>
----
- pyrpkg/__init__.py                    | 12 ++++++++++--
- tests/commands/test_pre_push_check.py |  4 ++--
- 2 files changed, 12 insertions(+), 4 deletions(-)
-
-diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py
-index b45ad8f..bc669b9 100644
---- a/pyrpkg/__init__.py
-+++ b/pyrpkg/__init__.py
-@@ -4468,6 +4468,10 @@ class Commands(object):
- 
-         return self._repo_name, version, release
- 
-+    # Works as virtual method. Other x-pkg tools can add their specific sources
-+    def additional_source_entries(self):
-+        return {}
-+
-     def pre_push_check(self, ref):
-         show_hint = ('Hint: this check (.git/hooks/pre-push script) can be bypassed by adding '
-                      'the argument \'--no-verify\' argument to the push command.')
-@@ -4561,13 +4565,17 @@ class Commands(object):
-         # list of all files (their relative paths) in the commit
-         repo_entries = set(item.path for item in commit.tree.traverse() if item.type != "tree")
- 
-+        # other x-pkg tools can add their specific sources
-+        additional_entries = set(self.additional_source_entries())
-+
-         # check whether every source file is either listed in the 'sources' file or tracked in git
-         for source_file in source_files:
-             listed = source_file in sourcesf_entries
-             tracked = source_file in repo_entries
--            if not (listed or tracked):
-+            listed_additional = source_file in additional_entries
-+            if not (listed or tracked or listed_additional):
-                 self.log.error('Source file \'{0}\' was neither listed in the \'sources\' file '
--                               'nor tracked in git. '
-+                               'nor tracked in git nor listed in additional sources. '
-                                'Push operation was cancelled'.format(source_file))
-                 self.log.warning(show_hint)
-                 sys.exit(4)
-diff --git a/tests/commands/test_pre_push_check.py b/tests/commands/test_pre_push_check.py
-index ee151c1..79165ec 100644
---- a/tests/commands/test_pre_push_check.py
-+++ b/tests/commands/test_pre_push_check.py
-@@ -90,8 +90,8 @@ Patch3: d.patch
- 
-         self.assertEqual(exc.exception.code, 4)
-         log_error.assert_called_once_with("Source file 'b.patch' was neither listed in the "
--                                          "'sources' file nor tracked in git. Push operation "
--                                          "was cancelled")
-+                                          "'sources' file nor tracked in git nor listed "
-+                                          "in additional sources. Push operation was cancelled")
- 
-         # Verify added files are committed but not pushed to origin
-         local_repo = git.Repo(self.cloned_dir)
--- 
-2.41.0
-

diff --git a/0025-Fix-flake8-complaints.patch b/0025-Fix-flake8-complaints.patch
deleted file mode 100644
index 0e4e657..0000000
--- a/0025-Fix-flake8-complaints.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-From 5c915a549ad2d10a3eb36c56801574d81a601670 Mon Sep 17 00:00:00 2001
-From: Ondrej Nosek <onosek@redhat.com>
-Date: Tue, 1 Aug 2023 23:26:43 +0200
-Subject: [PATCH 1/4] Fix flake8 complaints
-
-E721 do not compare types, for exact checks use `is` / `is not`, for
-instance checks use `isinstance()`
-Conditions in the method `_list_branches` were switched because:
-`issubclass(git.RemoteReference, git.Head)`
-
-Signed-off-by: Ondrej Nosek <onosek@redhat.com>
----
- pyrpkg/__init__.py | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
-diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py
-index bc669b9..f69f2ce 100644
---- a/pyrpkg/__init__.py
-+++ b/pyrpkg/__init__.py
-@@ -1411,15 +1411,15 @@ class Commands(object):
-         remotes = []
-         locals = []
-         for ref in refs:
--            if type(ref) == git.Head:
--                self.log.debug('Found local branch %s', ref.name)
--                locals.append(ref.name)
--            elif type(ref) == git.RemoteReference:
-+            if isinstance(ref, git.RemoteReference):
-                 if ref.remote_head == 'HEAD':
-                     self.log.debug('Skipping remote branch alias HEAD')
-                     continue  # Not useful in this context
-                 self.log.debug('Found remote branch %s', ref.name)
-                 remotes.append(ref.name)
-+            elif isinstance(ref, git.Head):
-+                self.log.debug('Found local branch %s', ref.name)
-+                locals.append(ref.name)
-         return (locals, remotes)
- 
-     def _srpmdetails(self, srpm):
--- 
-2.41.0
-

diff --git a/0025-Support-for-checking-exploded-sources-before-push.patch b/0025-Support-for-checking-exploded-sources-before-push.patch
new file mode 100644
index 0000000..cd1e34a
--- /dev/null
+++ b/0025-Support-for-checking-exploded-sources-before-push.patch
@@ -0,0 +1,71 @@
+From 87d4995b40fbcddac88fb21191eb2d5d1f248550 Mon Sep 17 00:00:00 2001
+From: Ondrej Nosek <onosek@redhat.com>
+Date: Tue, 11 Jul 2023 17:00:48 +0200
+Subject: [PATCH 04/17] Support for checking exploded sources before push
+
+pre-push-check now includes test whether source files listed
+in a specfile come from additional sources.
+This functionality is relevant only for some x-pkg tools, others
+should not be affected.
+
+JIRA: RHELCMP-11777
+
+Signed-off-by: Ondrej Nosek <onosek@redhat.com>
+---
+ pyrpkg/__init__.py                    | 12 ++++++++++--
+ tests/commands/test_pre_push_check.py |  4 ++--
+ 2 files changed, 12 insertions(+), 4 deletions(-)
+
+diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py
+index b45ad8f..bc669b9 100644
+--- a/pyrpkg/__init__.py
++++ b/pyrpkg/__init__.py
+@@ -4468,6 +4468,10 @@ class Commands(object):
+ 
+         return self._repo_name, version, release
+ 
++    # Works as virtual method. Other x-pkg tools can add their specific sources
++    def additional_source_entries(self):
++        return {}
++
+     def pre_push_check(self, ref):
+         show_hint = ('Hint: this check (.git/hooks/pre-push script) can be bypassed by adding '
+                      'the argument \'--no-verify\' argument to the push command.')
+@@ -4561,13 +4565,17 @@ class Commands(object):
+         # list of all files (their relative paths) in the commit
+         repo_entries = set(item.path for item in commit.tree.traverse() if item.type != "tree")
+ 
++        # other x-pkg tools can add their specific sources
++        additional_entries = set(self.additional_source_entries())
++
+         # check whether every source file is either listed in the 'sources' file or tracked in git
+         for source_file in source_files:
+             listed = source_file in sourcesf_entries
+             tracked = source_file in repo_entries
+-            if not (listed or tracked):
++            listed_additional = source_file in additional_entries
++            if not (listed or tracked or listed_additional):
+                 self.log.error('Source file \'{0}\' was neither listed in the \'sources\' file '
+-                               'nor tracked in git. '
++                               'nor tracked in git nor listed in additional sources. '
+                                'Push operation was cancelled'.format(source_file))
+                 self.log.warning(show_hint)
+                 sys.exit(4)
+diff --git a/tests/commands/test_pre_push_check.py b/tests/commands/test_pre_push_check.py
+index ee151c1..79165ec 100644
+--- a/tests/commands/test_pre_push_check.py
++++ b/tests/commands/test_pre_push_check.py
+@@ -90,8 +90,8 @@ Patch3: d.patch
+ 
+         self.assertEqual(exc.exception.code, 4)
+         log_error.assert_called_once_with("Source file 'b.patch' was neither listed in the "
+-                                          "'sources' file nor tracked in git. Push operation "
+-                                          "was cancelled")
++                                          "'sources' file nor tracked in git nor listed "
++                                          "in additional sources. Push operation was cancelled")
+ 
+         # Verify added files are committed but not pushed to origin
+         local_repo = git.Repo(self.cloned_dir)
+-- 
+2.43.0
+

diff --git a/0026-Fix-flake8-complaints.patch b/0026-Fix-flake8-complaints.patch
new file mode 100644
index 0000000..4955a49
--- /dev/null
+++ b/0026-Fix-flake8-complaints.patch
@@ -0,0 +1,42 @@
+From 5c915a549ad2d10a3eb36c56801574d81a601670 Mon Sep 17 00:00:00 2001
+From: Ondrej Nosek <onosek@redhat.com>
+Date: Tue, 1 Aug 2023 23:26:43 +0200
+Subject: [PATCH 05/17] Fix flake8 complaints
+
+E721 do not compare types, for exact checks use `is` / `is not`, for
+instance checks use `isinstance()`
+Conditions in the method `_list_branches` were switched because:
+`issubclass(git.RemoteReference, git.Head)`
+
+Signed-off-by: Ondrej Nosek <onosek@redhat.com>
+---
+ pyrpkg/__init__.py | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py
+index bc669b9..f69f2ce 100644
+--- a/pyrpkg/__init__.py
++++ b/pyrpkg/__init__.py
+@@ -1411,15 +1411,15 @@ class Commands(object):
+         remotes = []
+         locals = []
+         for ref in refs:
+-            if type(ref) == git.Head:
+-                self.log.debug('Found local branch %s', ref.name)
+-                locals.append(ref.name)
+-            elif type(ref) == git.RemoteReference:
++            if isinstance(ref, git.RemoteReference):
+                 if ref.remote_head == 'HEAD':
+                     self.log.debug('Skipping remote branch alias HEAD')
+                     continue  # Not useful in this context
+                 self.log.debug('Found remote branch %s', ref.name)
+                 remotes.append(ref.name)
++            elif isinstance(ref, git.Head):
++                self.log.debug('Found local branch %s', ref.name)
++                locals.append(ref.name)
+         return (locals, remotes)
+ 
+     def _srpmdetails(self, srpm):
+-- 
+2.43.0
+

diff --git a/0026-Prepare-the-lookaside-cache-code-for-retries.patch b/0026-Prepare-the-lookaside-cache-code-for-retries.patch
deleted file mode 100644
index 733a980..0000000
--- a/0026-Prepare-the-lookaside-cache-code-for-retries.patch
+++ /dev/null
@@ -1,148 +0,0 @@
-From 1a0601d29794cec1f735a10208364d11958c41ec Mon Sep 17 00:00:00 2001
-From: Ondrej Nosek <onosek@redhat.com>
-Date: Wed, 26 Jul 2023 01:30:12 +0200
-Subject: [PATCH 2/4] Prepare the lookaside cache code for retries
-
-These changes should not have an impact on the original functionality.
-
-JIRA: RHELCMP-11210
-
-Signed-off-by: Ondrej Nosek <onosek@redhat.com>
----
- pyrpkg/lookaside.py | 96 ++++++++++++++++++++++-----------------------
- 1 file changed, 48 insertions(+), 48 deletions(-)
-
-diff --git a/pyrpkg/lookaside.py b/pyrpkg/lookaside.py
-index 3efcd88..f94ffdb 100644
---- a/pyrpkg/lookaside.py
-+++ b/pyrpkg/lookaside.py
-@@ -163,17 +163,17 @@ class CGILookasideCache(object):
-             url = url.encode('utf-8')
-         self.log.debug("Full url: %s", url)
- 
-+        c = pycurl.Curl()
-+        c.setopt(pycurl.URL, url)
-+        c.setopt(pycurl.HTTPHEADER, ['Pragma:'])
-+        c.setopt(pycurl.NOPROGRESS, False)
-+        c.setopt(pycurl.PROGRESSFUNCTION, self.print_progress)
-+        c.setopt(pycurl.OPT_FILETIME, True)
-+        c.setopt(pycurl.LOW_SPEED_LIMIT, 1000)
-+        c.setopt(pycurl.LOW_SPEED_TIME, 300)
-+        c.setopt(pycurl.FOLLOWLOCATION, 1)
-         with open(outfile, 'wb') as f:
--            c = pycurl.Curl()
--            c.setopt(pycurl.URL, url)
--            c.setopt(pycurl.HTTPHEADER, ['Pragma:'])
--            c.setopt(pycurl.NOPROGRESS, False)
--            c.setopt(pycurl.PROGRESSFUNCTION, self.print_progress)
--            c.setopt(pycurl.OPT_FILETIME, True)
-             c.setopt(pycurl.WRITEDATA, f)
--            c.setopt(pycurl.LOW_SPEED_LIMIT, 1000)
--            c.setopt(pycurl.LOW_SPEED_TIME, 300)
--            c.setopt(pycurl.FOLLOWLOCATION, 1)
-             try:
-                 c.perform()
-                 tstamp = c.getinfo(pycurl.INFO_FILETIME)
-@@ -254,29 +254,29 @@ class CGILookasideCache(object):
-                      ('%ssum' % self.hashtype, hash),
-                      ('filename', filename)]
- 
--        with io.BytesIO() as buf:
--            c = pycurl.Curl()
--            c.setopt(pycurl.URL, self.upload_url)
--            c.setopt(pycurl.WRITEFUNCTION, buf.write)
--            c.setopt(pycurl.HTTPPOST, post_data)
--            c.setopt(pycurl.FOLLOWLOCATION, 1)
-+        c = pycurl.Curl()
-+        c.setopt(pycurl.URL, self.upload_url)
-+        c.setopt(pycurl.HTTPPOST, post_data)
-+        c.setopt(pycurl.FOLLOWLOCATION, 1)
- 
--            if self.client_cert is not None:
--                if os.path.exists(self.client_cert):
--                    c.setopt(pycurl.SSLCERT, self.client_cert)
--                else:
--                    self.log.warning("Missing certificate: %s"
--                                     % self.client_cert)
-+        if self.client_cert is not None:
-+            if os.path.exists(self.client_cert):
-+                c.setopt(pycurl.SSLCERT, self.client_cert)
-+            else:
-+                self.log.warning("Missing certificate: %s"
-+                                 % self.client_cert)
- 
--            if self.ca_cert is not None:
--                if os.path.exists(self.ca_cert):
--                    c.setopt(pycurl.CAINFO, self.ca_cert)
--                else:
--                    self.log.warning("Missing certificate: %s", self.ca_cert)
-+        if self.ca_cert is not None:
-+            if os.path.exists(self.ca_cert):
-+                c.setopt(pycurl.CAINFO, self.ca_cert)
-+            else:
-+                self.log.warning("Missing certificate: %s", self.ca_cert)
- 
--            c.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_GSSNEGOTIATE)
--            c.setopt(pycurl.USERPWD, ':')
-+        c.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_GSSNEGOTIATE)
-+        c.setopt(pycurl.USERPWD, ':')
- 
-+        with io.BytesIO() as buf:
-+            c.setopt(pycurl.WRITEFUNCTION, buf.write)
-             try:
-                 c.perform()
-                 status = c.getinfo(pycurl.RESPONSE_CODE)
-@@ -341,30 +341,30 @@ class CGILookasideCache(object):
-             ('mtime', str(int(os.stat(filepath).st_mtime))),
-         ]
- 
--        with io.BytesIO() as buf:
--            c = pycurl.Curl()
--            c.setopt(pycurl.URL, self.upload_url)
--            c.setopt(pycurl.NOPROGRESS, False)
--            c.setopt(pycurl.PROGRESSFUNCTION, self.print_progress)
--            c.setopt(pycurl.WRITEFUNCTION, buf.write)
--            c.setopt(pycurl.HTTPPOST, post_data)
--            c.setopt(pycurl.FOLLOWLOCATION, 1)
-+        c = pycurl.Curl()
-+        c.setopt(pycurl.URL, self.upload_url)
-+        c.setopt(pycurl.NOPROGRESS, False)
-+        c.setopt(pycurl.PROGRESSFUNCTION, self.print_progress)
-+        c.setopt(pycurl.HTTPPOST, post_data)
-+        c.setopt(pycurl.FOLLOWLOCATION, 1)
- 
--            if self.client_cert is not None:
--                if os.path.exists(self.client_cert):
--                    c.setopt(pycurl.SSLCERT, self.client_cert)
--                else:
--                    self.log.warning("Missing certificate: %s", self.client_cert)
-+        if self.client_cert is not None:
-+            if os.path.exists(self.client_cert):
-+                c.setopt(pycurl.SSLCERT, self.client_cert)
-+            else:
-+                self.log.warning("Missing certificate: %s", self.client_cert)
- 
--            if self.ca_cert is not None:
--                if os.path.exists(self.ca_cert):
--                    c.setopt(pycurl.CAINFO, self.ca_cert)
--                else:
--                    self.log.warning("Missing certificate: %s", self.ca_cert)
-+        if self.ca_cert is not None:
-+            if os.path.exists(self.ca_cert):
-+                c.setopt(pycurl.CAINFO, self.ca_cert)
-+            else:
-+                self.log.warning("Missing certificate: %s", self.ca_cert)
- 
--            c.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_GSSNEGOTIATE)
--            c.setopt(pycurl.USERPWD, ':')
-+        c.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_GSSNEGOTIATE)
-+        c.setopt(pycurl.USERPWD, ':')
- 
-+        with io.BytesIO() as buf:
-+            c.setopt(pycurl.WRITEFUNCTION, buf.write)
-             try:
-                 c.perform()
-                 status = c.getinfo(pycurl.RESPONSE_CODE)
--- 
-2.41.0
-

diff --git a/0027-Lookaside-cache-operations-retries.patch b/0027-Lookaside-cache-operations-retries.patch
deleted file mode 100644
index fe3a171..0000000
--- a/0027-Lookaside-cache-operations-retries.patch
+++ /dev/null
@@ -1,278 +0,0 @@
-From 3a96293d2479a75348f424806028c9b640aff31c Mon Sep 17 00:00:00 2001
-From: Ondrej Nosek <onosek@redhat.com>
-Date: Tue, 22 Aug 2023 14:48:02 +0200
-Subject: [PATCH 3/4] Lookaside cache operations retries
-
-Both upload and download network operations might fail
-and in this case, a retry mechanism was implemented.
-In case of failure, there is a delay and another attempt(s).
-Delays are increasing with every attempt.
-
-JIRA: RHELCMP-11210
-
-Signed-off-by: Ondrej Nosek <onosek@redhat.com>
----
- pyrpkg/lookaside.py     | 129 ++++++++++++++++++++++++++--------------
- tests/test_lookaside.py |  12 ++--
- 2 files changed, 89 insertions(+), 52 deletions(-)
-
-diff --git a/pyrpkg/lookaside.py b/pyrpkg/lookaside.py
-index f94ffdb..01eee4a 100644
---- a/pyrpkg/lookaside.py
-+++ b/pyrpkg/lookaside.py
-@@ -14,11 +14,13 @@ way it is done by Fedora, RHEL, and other distributions maintainers.
- """
- 
- 
-+import functools
- import hashlib
- import io
- import logging
- import os
- import sys
-+import time
- 
- import pycurl
- import six
-@@ -31,7 +33,7 @@ from .errors import (AlreadyUploadedError, DownloadError, InvalidHashType,
- class CGILookasideCache(object):
-     """A class to interact with a CGI-based lookaside cache"""
-     def __init__(self, hashtype, download_url, upload_url,
--                 client_cert=None, ca_cert=None):
-+                 client_cert=None, ca_cert=None, attempts=None, delay=None):
-         """Constructor
- 
-         :param str hashtype: The hash algorithm to use for uploads. (e.g 'md5')
-@@ -45,12 +47,18 @@ class CGILookasideCache(object):
-             use for HTTPS connexions. (e.g if the server certificate is
-             self-signed. It defaults to None, in which case the system CA
-             bundle is used.
-+        :param int attempts: repeat network operations after failure. The param
-+            says how many tries to do. None = single attempt / no-retrying
-+        :param int delay: Initial delay between network operation attempts.
-+            Each attempt doubles the previous delay value. In seconds.
-         """
-         self.hashtype = hashtype
-         self.download_url = download_url
-         self.upload_url = upload_url
-         self.client_cert = client_cert
-         self.ca_cert = ca_cert
-+        self.attempts = attempts if attempts is not None and attempts > 1 else 1
-+        self.delay_between_attempts = delay if delay is not None and delay >= 0 else 15
- 
-         self.log = logging.getLogger(__name__)
- 
-@@ -170,20 +178,13 @@ class CGILookasideCache(object):
-         c.setopt(pycurl.PROGRESSFUNCTION, self.print_progress)
-         c.setopt(pycurl.OPT_FILETIME, True)
-         c.setopt(pycurl.LOW_SPEED_LIMIT, 1000)
--        c.setopt(pycurl.LOW_SPEED_TIME, 300)
-+        c.setopt(pycurl.LOW_SPEED_TIME, 60)
-         c.setopt(pycurl.FOLLOWLOCATION, 1)
--        with open(outfile, 'wb') as f:
--            c.setopt(pycurl.WRITEDATA, f)
--            try:
--                c.perform()
--                tstamp = c.getinfo(pycurl.INFO_FILETIME)
--                status = c.getinfo(pycurl.RESPONSE_CODE)
--
--            except Exception as e:
--                raise DownloadError(e)
- 
--            finally:
--                c.close()
-+        # call retry method directly instead of @retry decorator - this approach allows passing
-+        # object's internal variables into the retry method
-+        status, tstamp = self.retry(raises=DownloadError)(self.retry_download)(c, outfile)
-+        c.close()
- 
-         # Get back a new line, after displaying the download progress
-         if sys.stdout.isatty():
-@@ -220,13 +221,8 @@ class CGILookasideCache(object):
-         c.setopt(pycurl.NOBODY, True)
-         c.setopt(pycurl.FOLLOWLOCATION, 1)
- 
--        try:
--            c.perform()
--            status = c.getinfo(pycurl.RESPONSE_CODE)
--        except Exception as e:
--            raise DownloadError(e)
--        finally:
--            c.close()
-+        status = self.retry(raises=DownloadError)(self.retry_remote_file_exists_head)(c)
-+        c.close()
- 
-         if status != 200:
-             self.log.debug('Unavailable file \'%s\' at %s' % (filename, url))
-@@ -275,19 +271,8 @@ class CGILookasideCache(object):
-         c.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_GSSNEGOTIATE)
-         c.setopt(pycurl.USERPWD, ':')
- 
--        with io.BytesIO() as buf:
--            c.setopt(pycurl.WRITEFUNCTION, buf.write)
--            try:
--                c.perform()
--                status = c.getinfo(pycurl.RESPONSE_CODE)
--
--            except Exception as e:
--                raise UploadError(e)
--
--            finally:
--                c.close()
--
--            output = buf.getvalue().strip()
-+        status, output = self.retry(raises=UploadError)(self.retry_remote_file_exists)(c)
-+        c.close()
- 
-         if status != 200:
-             self.raise_upload_error(status)
-@@ -363,19 +348,8 @@ class CGILookasideCache(object):
-         c.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_GSSNEGOTIATE)
-         c.setopt(pycurl.USERPWD, ':')
- 
--        with io.BytesIO() as buf:
--            c.setopt(pycurl.WRITEFUNCTION, buf.write)
--            try:
--                c.perform()
--                status = c.getinfo(pycurl.RESPONSE_CODE)
--
--            except Exception as e:
--                raise UploadError(e)
--
--            finally:
--                c.close()
--
--            output = buf.getvalue().strip()
-+        status, output = self.retry(raises=UploadError)(self.retry_upload)(c)
-+        c.close()
- 
-         # Get back a new line, after displaying the download progress
-         if sys.stdout.isatty():
-@@ -387,3 +361,66 @@ class CGILookasideCache(object):
- 
-         if output:
-             self.log.debug(output)
-+
-+    def retry_download(self, curl, outfile):
-+        with open(outfile, 'wb') as f:
-+            curl.setopt(pycurl.WRITEDATA, f)
-+            curl.perform()
-+            tstamp = curl.getinfo(pycurl.INFO_FILETIME)
-+            status = curl.getinfo(pycurl.RESPONSE_CODE)
-+        return status, tstamp
-+
-+    def retry_remote_file_exists_head(self, curl):
-+        curl.perform()
-+        status = curl.getinfo(pycurl.RESPONSE_CODE)
-+        return status
-+
-+    def retry_remote_file_exists(self, curl):
-+        with io.BytesIO() as buf:
-+            curl.setopt(pycurl.WRITEFUNCTION, buf.write)
-+            curl.perform()
-+            status = curl.getinfo(pycurl.RESPONSE_CODE)
-+            output = buf.getvalue().strip()
-+        return status, output
-+
-+    def retry_upload(self, curl):
-+        with io.BytesIO() as buf:
-+            curl.setopt(pycurl.WRITEFUNCTION, buf.write)
-+            curl.perform()
-+            status = curl.getinfo(pycurl.RESPONSE_CODE)
-+            output = buf.getvalue().strip()
-+        return status, output
-+
-+    def retry(self, attempts=None, delay_between_attempts=None, wait_on=pycurl.error, raises=None):
-+        """A decorator that allows to retry a section of code until success or counter elapses
-+        """
-+
-+        def wrapper(function):
-+            @functools.wraps(function)
-+            def inner(*args, **kwargs):
-+
-+                attempts_all = attempts or self.attempts
-+                attempts_left = attempts_all
-+                delay = delay_between_attempts or self.delay_between_attempts
-+                while attempts_left > 0:
-+                    try:
-+                        return function(*args, **kwargs)
-+                    except wait_on as e:
-+                        self.log.warn("Network error: %s" % (e))
-+                        attempts_left -= 1
-+                        self.log.debug("Attempt %d/%d has failed."
-+                                       % (attempts_all - attempts_left, attempts_all))
-+                        if attempts_left:
-+                            self.log.info("The operation will be retried in %ds." % (delay))
-+                            time.sleep(delay)
-+                            delay *= 2
-+                            self.log.info("Retrying ...")
-+                        else:
-+                            if raises is None:
-+                                raise  # This re-raises the last exception.
-+                            else:
-+                                raise raises(e)
-+
-+            return inner
-+
-+        return wrapper
-diff --git a/tests/test_lookaside.py b/tests/test_lookaside.py
-index 35d3499..2fe1bdb 100644
---- a/tests/test_lookaside.py
-+++ b/tests/test_lookaside.py
-@@ -175,7 +175,7 @@ class CGILookasideCacheTestCase(unittest.TestCase):
-             return 200 if info == pycurl.RESPONSE_CODE else 0
- 
-         def mock_perform():
--            with open(self.filename) as f:
-+            with open(self.filename, "rb") as f:
-                 curlopts[pycurl.WRITEDATA].write(f.read())
- 
-         def mock_setopt(opt, value):
-@@ -200,7 +200,7 @@ class CGILookasideCacheTestCase(unittest.TestCase):
-     @mock.patch('pyrpkg.lookaside.pycurl.Curl')
-     def test_download_failed(self, mock_curl):
-         curl = mock_curl.return_value
--        curl.perform.side_effect = Exception(
-+        curl.perform.side_effect = pycurl.error(
-             'Could not resolve host: example.com')
- 
-         with open(self.filename, 'wb') as f:
-@@ -219,7 +219,7 @@ class CGILookasideCacheTestCase(unittest.TestCase):
-             return 500 if info == pycurl.RESPONSE_CODE else 0
- 
-         def mock_perform():
--            with open(self.filename) as f:
-+            with open(self.filename, "rb") as f:
-                 curlopts[pycurl.WRITEDATA].write(f.read())
- 
-         def mock_setopt(opt, value):
-@@ -424,7 +424,7 @@ class CGILookasideCacheTestCase(unittest.TestCase):
-     @mock.patch('pyrpkg.lookaside.pycurl.Curl')
-     def test_remote_file_exists_check_failed(self, mock_curl):
-         curl = mock_curl.return_value
--        curl.perform.side_effect = Exception(
-+        curl.perform.side_effect = pycurl.error(
-             'Could not resolve host: example.com')
- 
-         lc = CGILookasideCache('_', '_', '_')
-@@ -452,7 +452,7 @@ class CGILookasideCacheTestCase(unittest.TestCase):
-     @mock.patch('pyrpkg.lookaside.pycurl.Curl')
-     def test_remote_file_exists_check_unexpected_error(self, mock_curl):
-         def mock_perform():
--            curlopts[pycurl.WRITEFUNCTION]('Something unexpected')
-+            curlopts[pycurl.WRITEFUNCTION](b'Something unexpected')
- 
-         def mock_setopt(opt, value):
-             curlopts[opt] = value
-@@ -590,7 +590,7 @@ class CGILookasideCacheTestCase(unittest.TestCase):
-     @mock.patch('pyrpkg.lookaside.pycurl.Curl')
-     def test_upload_failed(self, mock_curl):
-         curl = mock_curl.return_value
--        curl.perform.side_effect = Exception(
-+        curl.perform.side_effect = pycurl.error(
-             'Could not resolve host: example.com')
- 
-         lc = CGILookasideCache('_', '_', '_')
--- 
-2.41.0
-

diff --git a/0027-Prepare-the-lookaside-cache-code-for-retries.patch b/0027-Prepare-the-lookaside-cache-code-for-retries.patch
new file mode 100644
index 0000000..48a5962
--- /dev/null
+++ b/0027-Prepare-the-lookaside-cache-code-for-retries.patch
@@ -0,0 +1,148 @@
+From 1a0601d29794cec1f735a10208364d11958c41ec Mon Sep 17 00:00:00 2001
+From: Ondrej Nosek <onosek@redhat.com>
+Date: Wed, 26 Jul 2023 01:30:12 +0200
+Subject: [PATCH 06/17] Prepare the lookaside cache code for retries
+
+These changes should not have an impact on the original functionality.
+
+JIRA: RHELCMP-11210
+
+Signed-off-by: Ondrej Nosek <onosek@redhat.com>
+---
+ pyrpkg/lookaside.py | 96 ++++++++++++++++++++++-----------------------
+ 1 file changed, 48 insertions(+), 48 deletions(-)
+
+diff --git a/pyrpkg/lookaside.py b/pyrpkg/lookaside.py
+index 3efcd88..f94ffdb 100644
+--- a/pyrpkg/lookaside.py
++++ b/pyrpkg/lookaside.py
+@@ -163,17 +163,17 @@ class CGILookasideCache(object):
+             url = url.encode('utf-8')
+         self.log.debug("Full url: %s", url)
+ 
++        c = pycurl.Curl()
++        c.setopt(pycurl.URL, url)
++        c.setopt(pycurl.HTTPHEADER, ['Pragma:'])
++        c.setopt(pycurl.NOPROGRESS, False)
++        c.setopt(pycurl.PROGRESSFUNCTION, self.print_progress)
++        c.setopt(pycurl.OPT_FILETIME, True)
++        c.setopt(pycurl.LOW_SPEED_LIMIT, 1000)
++        c.setopt(pycurl.LOW_SPEED_TIME, 300)
++        c.setopt(pycurl.FOLLOWLOCATION, 1)
+         with open(outfile, 'wb') as f:
+-            c = pycurl.Curl()
+-            c.setopt(pycurl.URL, url)
+-            c.setopt(pycurl.HTTPHEADER, ['Pragma:'])
+-            c.setopt(pycurl.NOPROGRESS, False)
+-            c.setopt(pycurl.PROGRESSFUNCTION, self.print_progress)
+-            c.setopt(pycurl.OPT_FILETIME, True)
+             c.setopt(pycurl.WRITEDATA, f)
+-            c.setopt(pycurl.LOW_SPEED_LIMIT, 1000)
+-            c.setopt(pycurl.LOW_SPEED_TIME, 300)
+-            c.setopt(pycurl.FOLLOWLOCATION, 1)
+             try:
+                 c.perform()
+                 tstamp = c.getinfo(pycurl.INFO_FILETIME)
+@@ -254,29 +254,29 @@ class CGILookasideCache(object):
+                      ('%ssum' % self.hashtype, hash),
+                      ('filename', filename)]
+ 
+-        with io.BytesIO() as buf:
+-            c = pycurl.Curl()
+-            c.setopt(pycurl.URL, self.upload_url)
+-            c.setopt(pycurl.WRITEFUNCTION, buf.write)
+-            c.setopt(pycurl.HTTPPOST, post_data)
+-            c.setopt(pycurl.FOLLOWLOCATION, 1)
++        c = pycurl.Curl()
++        c.setopt(pycurl.URL, self.upload_url)
++        c.setopt(pycurl.HTTPPOST, post_data)
++        c.setopt(pycurl.FOLLOWLOCATION, 1)
+ 
+-            if self.client_cert is not None:
+-                if os.path.exists(self.client_cert):
+-                    c.setopt(pycurl.SSLCERT, self.client_cert)
+-                else:
+-                    self.log.warning("Missing certificate: %s"
+-                                     % self.client_cert)
++        if self.client_cert is not None:
++            if os.path.exists(self.client_cert):
++                c.setopt(pycurl.SSLCERT, self.client_cert)
++            else:
++                self.log.warning("Missing certificate: %s"
++                                 % self.client_cert)
+ 
+-            if self.ca_cert is not None:
+-                if os.path.exists(self.ca_cert):
+-                    c.setopt(pycurl.CAINFO, self.ca_cert)
+-                else:
+-                    self.log.warning("Missing certificate: %s", self.ca_cert)
++        if self.ca_cert is not None:
++            if os.path.exists(self.ca_cert):
++                c.setopt(pycurl.CAINFO, self.ca_cert)
++            else:
++                self.log.warning("Missing certificate: %s", self.ca_cert)
+ 
+-            c.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_GSSNEGOTIATE)
+-            c.setopt(pycurl.USERPWD, ':')
++        c.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_GSSNEGOTIATE)
++        c.setopt(pycurl.USERPWD, ':')
+ 
++        with io.BytesIO() as buf:
++            c.setopt(pycurl.WRITEFUNCTION, buf.write)
+             try:
+                 c.perform()
+                 status = c.getinfo(pycurl.RESPONSE_CODE)
+@@ -341,30 +341,30 @@ class CGILookasideCache(object):
+             ('mtime', str(int(os.stat(filepath).st_mtime))),
+         ]
+ 
+-        with io.BytesIO() as buf:
+-            c = pycurl.Curl()
+-            c.setopt(pycurl.URL, self.upload_url)
+-            c.setopt(pycurl.NOPROGRESS, False)
+-            c.setopt(pycurl.PROGRESSFUNCTION, self.print_progress)
+-            c.setopt(pycurl.WRITEFUNCTION, buf.write)
+-            c.setopt(pycurl.HTTPPOST, post_data)
+-            c.setopt(pycurl.FOLLOWLOCATION, 1)
++        c = pycurl.Curl()
++        c.setopt(pycurl.URL, self.upload_url)
++        c.setopt(pycurl.NOPROGRESS, False)
++        c.setopt(pycurl.PROGRESSFUNCTION, self.print_progress)
++        c.setopt(pycurl.HTTPPOST, post_data)
++        c.setopt(pycurl.FOLLOWLOCATION, 1)
+ 
+-            if self.client_cert is not None:
+-                if os.path.exists(self.client_cert):
+-                    c.setopt(pycurl.SSLCERT, self.client_cert)
+-                else:
+-                    self.log.warning("Missing certificate: %s", self.client_cert)
++        if self.client_cert is not None:
++            if os.path.exists(self.client_cert):
++                c.setopt(pycurl.SSLCERT, self.client_cert)
++            else:
++                self.log.warning("Missing certificate: %s", self.client_cert)
+ 
+-            if self.ca_cert is not None:
+-                if os.path.exists(self.ca_cert):
+-                    c.setopt(pycurl.CAINFO, self.ca_cert)
+-                else:
+-                    self.log.warning("Missing certificate: %s", self.ca_cert)
++        if self.ca_cert is not None:
++            if os.path.exists(self.ca_cert):
++                c.setopt(pycurl.CAINFO, self.ca_cert)
++            else:
++                self.log.warning("Missing certificate: %s", self.ca_cert)
+ 
+-            c.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_GSSNEGOTIATE)
+-            c.setopt(pycurl.USERPWD, ':')
++        c.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_GSSNEGOTIATE)
++        c.setopt(pycurl.USERPWD, ':')
+ 
++        with io.BytesIO() as buf:
++            c.setopt(pycurl.WRITEFUNCTION, buf.write)
+             try:
+                 c.perform()
+                 status = c.getinfo(pycurl.RESPONSE_CODE)
+-- 
+2.43.0
+

diff --git a/0028-Lookaside-cache-operations-retries.patch b/0028-Lookaside-cache-operations-retries.patch
new file mode 100644
index 0000000..82c98cd
--- /dev/null
+++ b/0028-Lookaside-cache-operations-retries.patch
@@ -0,0 +1,278 @@
+From 3a96293d2479a75348f424806028c9b640aff31c Mon Sep 17 00:00:00 2001
+From: Ondrej Nosek <onosek@redhat.com>
+Date: Tue, 22 Aug 2023 14:48:02 +0200
+Subject: [PATCH 07/17] Lookaside cache operations retries
+
+Both upload and download network operations might fail
+and in this case, a retry mechanism was implemented.
+In case of failure, there is a delay and another attempt(s).
+Delays are increasing with every attempt.
+
+JIRA: RHELCMP-11210
+
+Signed-off-by: Ondrej Nosek <onosek@redhat.com>
+---
+ pyrpkg/lookaside.py     | 129 ++++++++++++++++++++++++++--------------
+ tests/test_lookaside.py |  12 ++--
+ 2 files changed, 89 insertions(+), 52 deletions(-)
+
+diff --git a/pyrpkg/lookaside.py b/pyrpkg/lookaside.py
+index f94ffdb..01eee4a 100644
+--- a/pyrpkg/lookaside.py
++++ b/pyrpkg/lookaside.py
+@@ -14,11 +14,13 @@ way it is done by Fedora, RHEL, and other distributions maintainers.
+ """
+ 
+ 
++import functools
+ import hashlib
+ import io
+ import logging
+ import os
+ import sys
++import time
+ 
+ import pycurl
+ import six
+@@ -31,7 +33,7 @@ from .errors import (AlreadyUploadedError, DownloadError, InvalidHashType,
+ class CGILookasideCache(object):
+     """A class to interact with a CGI-based lookaside cache"""
+     def __init__(self, hashtype, download_url, upload_url,
+-                 client_cert=None, ca_cert=None):
++                 client_cert=None, ca_cert=None, attempts=None, delay=None):
+         """Constructor
+ 
+         :param str hashtype: The hash algorithm to use for uploads. (e.g 'md5')
+@@ -45,12 +47,18 @@ class CGILookasideCache(object):
+             use for HTTPS connexions. (e.g if the server certificate is
+             self-signed. It defaults to None, in which case the system CA
+             bundle is used.
++        :param int attempts: repeat network operations after failure. The param
++            says how many tries to do. None = single attempt / no-retrying
++        :param int delay: Initial delay between network operation attempts.
++            Each attempt doubles the previous delay value. In seconds.
+         """
+         self.hashtype = hashtype
+         self.download_url = download_url
+         self.upload_url = upload_url
+         self.client_cert = client_cert
+         self.ca_cert = ca_cert
++        self.attempts = attempts if attempts is not None and attempts > 1 else 1
++        self.delay_between_attempts = delay if delay is not None and delay >= 0 else 15
+ 
+         self.log = logging.getLogger(__name__)
+ 
+@@ -170,20 +178,13 @@ class CGILookasideCache(object):
+         c.setopt(pycurl.PROGRESSFUNCTION, self.print_progress)
+         c.setopt(pycurl.OPT_FILETIME, True)
+         c.setopt(pycurl.LOW_SPEED_LIMIT, 1000)
+-        c.setopt(pycurl.LOW_SPEED_TIME, 300)
++        c.setopt(pycurl.LOW_SPEED_TIME, 60)
+         c.setopt(pycurl.FOLLOWLOCATION, 1)
+-        with open(outfile, 'wb') as f:
+-            c.setopt(pycurl.WRITEDATA, f)
+-            try:
+-                c.perform()
+-                tstamp = c.getinfo(pycurl.INFO_FILETIME)
+-                status = c.getinfo(pycurl.RESPONSE_CODE)
+-
+-            except Exception as e:
+-                raise DownloadError(e)
+ 
+-            finally:
+-                c.close()
++        # call retry method directly instead of @retry decorator - this approach allows passing
++        # object's internal variables into the retry method
++        status, tstamp = self.retry(raises=DownloadError)(self.retry_download)(c, outfile)
++        c.close()
+ 
+         # Get back a new line, after displaying the download progress
+         if sys.stdout.isatty():
+@@ -220,13 +221,8 @@ class CGILookasideCache(object):
+         c.setopt(pycurl.NOBODY, True)
+         c.setopt(pycurl.FOLLOWLOCATION, 1)
+ 
+-        try:
+-            c.perform()
+-            status = c.getinfo(pycurl.RESPONSE_CODE)
+-        except Exception as e:
+-            raise DownloadError(e)
+-        finally:
+-            c.close()
++        status = self.retry(raises=DownloadError)(self.retry_remote_file_exists_head)(c)
++        c.close()
+ 
+         if status != 200:
+             self.log.debug('Unavailable file \'%s\' at %s' % (filename, url))
+@@ -275,19 +271,8 @@ class CGILookasideCache(object):
+         c.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_GSSNEGOTIATE)
+         c.setopt(pycurl.USERPWD, ':')
+ 
+-        with io.BytesIO() as buf:
+-            c.setopt(pycurl.WRITEFUNCTION, buf.write)
+-            try:
+-                c.perform()
+-                status = c.getinfo(pycurl.RESPONSE_CODE)
+-
+-            except Exception as e:
+-                raise UploadError(e)
+-
+-            finally:
+-                c.close()
+-
+-            output = buf.getvalue().strip()
++        status, output = self.retry(raises=UploadError)(self.retry_remote_file_exists)(c)
++        c.close()
+ 
+         if status != 200:
+             self.raise_upload_error(status)
+@@ -363,19 +348,8 @@ class CGILookasideCache(object):
+         c.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_GSSNEGOTIATE)
+         c.setopt(pycurl.USERPWD, ':')
+ 
+-        with io.BytesIO() as buf:
+-            c.setopt(pycurl.WRITEFUNCTION, buf.write)
+-            try:
+-                c.perform()
+-                status = c.getinfo(pycurl.RESPONSE_CODE)
+-
+-            except Exception as e:
+-                raise UploadError(e)
+-
+-            finally:
+-                c.close()
+-
+-            output = buf.getvalue().strip()
++        status, output = self.retry(raises=UploadError)(self.retry_upload)(c)
++        c.close()
+ 
+         # Get back a new line, after displaying the download progress
+         if sys.stdout.isatty():
+@@ -387,3 +361,66 @@ class CGILookasideCache(object):
+ 
+         if output:
+             self.log.debug(output)
++
++    def retry_download(self, curl, outfile):
++        with open(outfile, 'wb') as f:
++            curl.setopt(pycurl.WRITEDATA, f)
++            curl.perform()
++            tstamp = curl.getinfo(pycurl.INFO_FILETIME)
++            status = curl.getinfo(pycurl.RESPONSE_CODE)
++        return status, tstamp
++
++    def retry_remote_file_exists_head(self, curl):
++        curl.perform()
++        status = curl.getinfo(pycurl.RESPONSE_CODE)
++        return status
++
++    def retry_remote_file_exists(self, curl):
++        with io.BytesIO() as buf:
++            curl.setopt(pycurl.WRITEFUNCTION, buf.write)
++            curl.perform()
++            status = curl.getinfo(pycurl.RESPONSE_CODE)
++            output = buf.getvalue().strip()
++        return status, output
++
++    def retry_upload(self, curl):
++        with io.BytesIO() as buf:
++            curl.setopt(pycurl.WRITEFUNCTION, buf.write)
++            curl.perform()
++            status = curl.getinfo(pycurl.RESPONSE_CODE)
++            output = buf.getvalue().strip()
++        return status, output
++
++    def retry(self, attempts=None, delay_between_attempts=None, wait_on=pycurl.error, raises=None):
++        """A decorator that allows to retry a section of code until success or counter elapses
++        """
++
++        def wrapper(function):
++            @functools.wraps(function)
++            def inner(*args, **kwargs):
++
++                attempts_all = attempts or self.attempts
++                attempts_left = attempts_all
++                delay = delay_between_attempts or self.delay_between_attempts
++                while attempts_left > 0:
++                    try:
++                        return function(*args, **kwargs)
++                    except wait_on as e:
++                        self.log.warn("Network error: %s" % (e))
++                        attempts_left -= 1
++                        self.log.debug("Attempt %d/%d has failed."
++                                       % (attempts_all - attempts_left, attempts_all))
++                        if attempts_left:
++                            self.log.info("The operation will be retried in %ds." % (delay))
++                            time.sleep(delay)
++                            delay *= 2
++                            self.log.info("Retrying ...")
++                        else:
++                            if raises is None:
++                                raise  # This re-raises the last exception.
++                            else:
++                                raise raises(e)
++
++            return inner
++
++        return wrapper
+diff --git a/tests/test_lookaside.py b/tests/test_lookaside.py
+index 35d3499..2fe1bdb 100644
+--- a/tests/test_lookaside.py
++++ b/tests/test_lookaside.py
+@@ -175,7 +175,7 @@ class CGILookasideCacheTestCase(unittest.TestCase):
+             return 200 if info == pycurl.RESPONSE_CODE else 0
+ 
+         def mock_perform():
+-            with open(self.filename) as f:
++            with open(self.filename, "rb") as f:
+                 curlopts[pycurl.WRITEDATA].write(f.read())
+ 
+         def mock_setopt(opt, value):
+@@ -200,7 +200,7 @@ class CGILookasideCacheTestCase(unittest.TestCase):
+     @mock.patch('pyrpkg.lookaside.pycurl.Curl')
+     def test_download_failed(self, mock_curl):
+         curl = mock_curl.return_value
+-        curl.perform.side_effect = Exception(
++        curl.perform.side_effect = pycurl.error(
+             'Could not resolve host: example.com')
+ 
+         with open(self.filename, 'wb') as f:
+@@ -219,7 +219,7 @@ class CGILookasideCacheTestCase(unittest.TestCase):
+             return 500 if info == pycurl.RESPONSE_CODE else 0
+ 
+         def mock_perform():
+-            with open(self.filename) as f:
++            with open(self.filename, "rb") as f:
+                 curlopts[pycurl.WRITEDATA].write(f.read())
+ 
+         def mock_setopt(opt, value):
+@@ -424,7 +424,7 @@ class CGILookasideCacheTestCase(unittest.TestCase):
+     @mock.patch('pyrpkg.lookaside.pycurl.Curl')
+     def test_remote_file_exists_check_failed(self, mock_curl):
+         curl = mock_curl.return_value
+-        curl.perform.side_effect = Exception(
++        curl.perform.side_effect = pycurl.error(
+             'Could not resolve host: example.com')
+ 
+         lc = CGILookasideCache('_', '_', '_')
+@@ -452,7 +452,7 @@ class CGILookasideCacheTestCase(unittest.TestCase):
+     @mock.patch('pyrpkg.lookaside.pycurl.Curl')
+     def test_remote_file_exists_check_unexpected_error(self, mock_curl):
+         def mock_perform():
+-            curlopts[pycurl.WRITEFUNCTION]('Something unexpected')
++            curlopts[pycurl.WRITEFUNCTION](b'Something unexpected')
+ 
+         def mock_setopt(opt, value):
+             curlopts[opt] = value
+@@ -590,7 +590,7 @@ class CGILookasideCacheTestCase(unittest.TestCase):
+     @mock.patch('pyrpkg.lookaside.pycurl.Curl')
+     def test_upload_failed(self, mock_curl):
+         curl = mock_curl.return_value
+-        curl.perform.side_effect = Exception(
++        curl.perform.side_effect = pycurl.error(
+             'Could not resolve host: example.com')
+ 
+         lc = CGILookasideCache('_', '_', '_')
+-- 
+2.43.0
+

diff --git a/0028-Make-lookaside-cache-retries-configurable.patch b/0028-Make-lookaside-cache-retries-configurable.patch
deleted file mode 100644
index f2fcfd5..0000000
--- a/0028-Make-lookaside-cache-retries-configurable.patch
+++ /dev/null
@@ -1,108 +0,0 @@
-From 08cebe5fae426c11b51e645754b87e4ec5737ef3 Mon Sep 17 00:00:00 2001
-From: Ondrej Nosek <onosek@redhat.com>
-Date: Tue, 22 Aug 2023 22:22:03 +0200
-Subject: [PATCH 4/4] Make lookaside cache retries configurable
-
-The number of attempts for lookaside cache network operations is now
-configurable - there are new keys 'lookaside_attempts'
-and 'lookaside_delay' in the configuration.
-The Former expresses a maximum number of attempts to try the operation.
-'0' or '1' is for a single try (no-retry).
-The latter means an initial delay between network operation attempts.
-Each attempt doubles the previous delay value. In seconds.
-
-JIRA: RHELCMP-11210
-
-Signed-off-by: Ondrej Nosek <onosek@redhat.com>
----
- pyrpkg/__init__.py | 10 ++++++++--
- pyrpkg/cli.py      | 34 +++++++++++++++++++++++++++++++++-
- 2 files changed, 41 insertions(+), 3 deletions(-)
-
-diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py
-index f69f2ce..5928d47 100644
---- a/pyrpkg/__init__.py
-+++ b/pyrpkg/__init__.py
-@@ -110,7 +110,8 @@ class Commands(object):
-                  build_client, user=None,
-                  dist=None, target=None, quiet=False,
-                  distgit_namespaced=False, realms=None, lookaside_namespaced=False,
--                 git_excludes=None, results_dir='root', allow_pre_generated_srpm=False):
-+                 git_excludes=None, results_dir='root', allow_pre_generated_srpm=False,
-+                 lookaside_attempts=None, lookaside_delay=None):
-         """Init the object and some configuration details."""
- 
-         # Path to operate on, most often pwd
-@@ -242,6 +243,10 @@ class Commands(object):
-         # A Configuration value used in 'import_srpm' command (comes from the Copr team)
-         # If pre-generated srpms are allowed, don't care specfile is processed by rpmautospec
-         self.allow_pre_generated_srpm = allow_pre_generated_srpm
-+        # number of attempts for lookaside network operations
-+        self.lookaside_attempts = lookaside_attempts
-+        # initial delay between network operation attempts. In seconds.
-+        self.lookaside_delay = lookaside_delay
- 
-     # Define properties here
-     # Properties allow us to "lazy load" various attributes, which also means
-@@ -262,7 +267,8 @@ class Commands(object):
-         """
-         return CGILookasideCache(
-             self.lookasidehash, self.lookaside, self.lookaside_cgi,
--            client_cert=self.cert_file, ca_cert=self.ca_cert)
-+            client_cert=self.cert_file, ca_cert=self.ca_cert,
-+            attempts=self.lookaside_attempts, delay=self.lookaside_delay)
- 
-     @property
-     def path(self):
-diff --git a/pyrpkg/cli.py b/pyrpkg/cli.py
-index 1bd7979..16298f0 100644
---- a/pyrpkg/cli.py
-+++ b/pyrpkg/cli.py
-@@ -261,7 +261,9 @@ class cliClient(object):
-                                        realms=realms,
-                                        lookaside_namespaced=la_namespaced,
-                                        git_excludes=git_excludes,
--                                       results_dir=results_dir
-+                                       results_dir=results_dir,
-+                                       lookaside_attempts=self.lookaside_attempts,
-+                                       lookaside_delay=self.lookaside_delay
-                                        )
- 
-         if self.args.repo_name:
-@@ -3087,3 +3089,33 @@ class cliClient(object):
- 
-     def pre_push_check(self):
-         self.cmd.pre_push_check(self.args.ref)
-+
-+    @property
-+    def lookaside_attempts(self):
-+        """loads parameter 'lookaside_attempts' from the config file
-+        """
-+        val = None
-+        if self.config.has_option(self.name, 'lookaside_attempts'):
-+            val = self.config.get(self.name, 'lookaside_attempts')
-+            try:
-+                val = int(val)
-+            except Exception:
-+                self.log.error("Error: The config value 'lookaside_attempts' "
-+                               "should be an integer.")
-+                val = None
-+        return val
-+
-+    @property
-+    def lookaside_delay(self):
-+        """loads parameter 'lookaside_delay' from the config file
-+        """
-+        val = None
-+        if self.config.has_option(self.name, 'lookaside_delay'):
-+            val = self.config.get(self.name, 'lookaside_delay')
-+            try:
-+                val = int(val)
-+            except Exception:
-+                self.log.error("Error: The config value 'lookaside_delay' "
-+                               "should be an integer.")
-+                val = None
-+        return val
--- 
-2.41.0
-

diff --git a/0029-Make-lookaside-cache-retries-configurable.patch b/0029-Make-lookaside-cache-retries-configurable.patch
new file mode 100644
index 0000000..61fc41c
--- /dev/null
+++ b/0029-Make-lookaside-cache-retries-configurable.patch
@@ -0,0 +1,108 @@
+From 08cebe5fae426c11b51e645754b87e4ec5737ef3 Mon Sep 17 00:00:00 2001
+From: Ondrej Nosek <onosek@redhat.com>
+Date: Tue, 22 Aug 2023 22:22:03 +0200
+Subject: [PATCH 08/17] Make lookaside cache retries configurable
+
+The number of attempts for lookaside cache network operations is now
+configurable - there are new keys 'lookaside_attempts'
+and 'lookaside_delay' in the configuration.
+The Former expresses a maximum number of attempts to try the operation.
+'0' or '1' is for a single try (no-retry).
+The latter means an initial delay between network operation attempts.
+Each attempt doubles the previous delay value. In seconds.
+
+JIRA: RHELCMP-11210
+
+Signed-off-by: Ondrej Nosek <onosek@redhat.com>
+---
+ pyrpkg/__init__.py | 10 ++++++++--
+ pyrpkg/cli.py      | 34 +++++++++++++++++++++++++++++++++-
+ 2 files changed, 41 insertions(+), 3 deletions(-)
+
+diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py
+index f69f2ce..5928d47 100644
+--- a/pyrpkg/__init__.py
++++ b/pyrpkg/__init__.py
+@@ -110,7 +110,8 @@ class Commands(object):
+                  build_client, user=None,
+                  dist=None, target=None, quiet=False,
+                  distgit_namespaced=False, realms=None, lookaside_namespaced=False,
+-                 git_excludes=None, results_dir='root', allow_pre_generated_srpm=False):
++                 git_excludes=None, results_dir='root', allow_pre_generated_srpm=False,
++                 lookaside_attempts=None, lookaside_delay=None):
+         """Init the object and some configuration details."""
+ 
+         # Path to operate on, most often pwd
+@@ -242,6 +243,10 @@ class Commands(object):
+         # A Configuration value used in 'import_srpm' command (comes from the Copr team)
+         # If pre-generated srpms are allowed, don't care specfile is processed by rpmautospec
+         self.allow_pre_generated_srpm = allow_pre_generated_srpm
++        # number of attempts for lookaside network operations
++        self.lookaside_attempts = lookaside_attempts
++        # initial delay between network operation attempts. In seconds.
++        self.lookaside_delay = lookaside_delay
+ 
+     # Define properties here
+     # Properties allow us to "lazy load" various attributes, which also means
+@@ -262,7 +267,8 @@ class Commands(object):
+         """
+         return CGILookasideCache(
+             self.lookasidehash, self.lookaside, self.lookaside_cgi,
+-            client_cert=self.cert_file, ca_cert=self.ca_cert)
++            client_cert=self.cert_file, ca_cert=self.ca_cert,
++            attempts=self.lookaside_attempts, delay=self.lookaside_delay)
+ 
+     @property
+     def path(self):
+diff --git a/pyrpkg/cli.py b/pyrpkg/cli.py
+index 1bd7979..16298f0 100644
+--- a/pyrpkg/cli.py
++++ b/pyrpkg/cli.py
+@@ -261,7 +261,9 @@ class cliClient(object):
+                                        realms=realms,
+                                        lookaside_namespaced=la_namespaced,
+                                        git_excludes=git_excludes,
+-                                       results_dir=results_dir
++                                       results_dir=results_dir,
++                                       lookaside_attempts=self.lookaside_attempts,
++                                       lookaside_delay=self.lookaside_delay
+                                        )
+ 
+         if self.args.repo_name:
+@@ -3087,3 +3089,33 @@ class cliClient(object):
+ 
+     def pre_push_check(self):
+         self.cmd.pre_push_check(self.args.ref)
++
++    @property
++    def lookaside_attempts(self):
++        """loads parameter 'lookaside_attempts' from the config file
++        """
++        val = None
++        if self.config.has_option(self.name, 'lookaside_attempts'):
++            val = self.config.get(self.name, 'lookaside_attempts')
++            try:
++                val = int(val)
++            except Exception:
++                self.log.error("Error: The config value 'lookaside_attempts' "
++                               "should be an integer.")
++                val = None
++        return val
++
++    @property
++    def lookaside_delay(self):
++        """loads parameter 'lookaside_delay' from the config file
++        """
++        val = None
++        if self.config.has_option(self.name, 'lookaside_delay'):
++            val = self.config.get(self.name, 'lookaside_delay')
++            try:
++                val = int(val)
++            except Exception:
++                self.log.error("Error: The config value 'lookaside_delay' "
++                               "should be an integer.")
++                val = None
++        return val
+-- 
+2.43.0
+

diff --git a/0029-pkg-import-Don-t-delete-changelog-generated-by-rpmau.patch b/0029-pkg-import-Don-t-delete-changelog-generated-by-rpmau.patch
deleted file mode 100644
index 7f9685a..0000000
--- a/0029-pkg-import-Don-t-delete-changelog-generated-by-rpmau.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From 2fdb7806aa947d4997aea6cb33f3e893a2b7d876 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= <miro@hroncok.cz>
-Date: Thu, 5 Oct 2023 17:03:39 +0200
-Subject: [PATCH 1/5] *pkg import: Don't delete changelog generated by
- `rpmautospec convert`
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Miro Hrončok <miro@hroncok.cz>
----
- pyrpkg/__init__.py | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py
-index 5928d47..b257fec 100644
---- a/pyrpkg/__init__.py
-+++ b/pyrpkg/__init__.py
-@@ -2040,7 +2040,7 @@ class Commands(object):
-         # not be removed by import command.
-         reserved_ourfiles = [
-             'README.md', 'gating.yaml', 'tests/*', '*.rpmlintrc',
--            '.fmf/*', '*.fmf']
-+            '.fmf/*', '*.fmf', 'changelog']
- 
-         # Get a list of files we're currently tracking
-         ourfiles = self.repo.git.ls_files().split('\n')
--- 
-2.41.0
-

diff --git a/0030-pkg-import-Don-t-delete-changelog-generated-by-rpmau.patch b/0030-pkg-import-Don-t-delete-changelog-generated-by-rpmau.patch
new file mode 100644
index 0000000..f3bd9be
--- /dev/null
+++ b/0030-pkg-import-Don-t-delete-changelog-generated-by-rpmau.patch
@@ -0,0 +1,30 @@
+From 2fdb7806aa947d4997aea6cb33f3e893a2b7d876 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= <miro@hroncok.cz>
+Date: Thu, 5 Oct 2023 17:03:39 +0200
+Subject: [PATCH 09/17] *pkg import: Don't delete changelog generated by
+ `rpmautospec convert`
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Miro Hrončok <miro@hroncok.cz>
+---
+ pyrpkg/__init__.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py
+index 5928d47..b257fec 100644
+--- a/pyrpkg/__init__.py
++++ b/pyrpkg/__init__.py
+@@ -2040,7 +2040,7 @@ class Commands(object):
+         # not be removed by import command.
+         reserved_ourfiles = [
+             'README.md', 'gating.yaml', 'tests/*', '*.rpmlintrc',
+-            '.fmf/*', '*.fmf']
++            '.fmf/*', '*.fmf', 'changelog']
+ 
+         # Get a list of files we're currently tracking
+         ourfiles = self.repo.git.ls_files().split('\n')
+-- 
+2.43.0
+

diff --git a/0030-pkg-import-Undo-rpmautospec-processing.patch b/0030-pkg-import-Undo-rpmautospec-processing.patch
deleted file mode 100644
index 131e076..0000000
--- a/0030-pkg-import-Undo-rpmautospec-processing.patch
+++ /dev/null
@@ -1,162 +0,0 @@
-From ebb5c4b82caec5160544fdbb2d539fd1b5a3abfb Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= <miro@hroncok.cz>
-Date: Thu, 5 Oct 2023 16:59:22 +0200
-Subject: [PATCH 2/5] *pkg import: Undo rpmautospec processing
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Fixes https://pagure.io/fedpkg/issue/527
-
-Depends-on: https://pagure.io/fedora-infra/rpmautospec/pull-request/312
-
-Signed-off-by: Miro Hrončok <miro@hroncok.cz>
----
- pyrpkg/__init__.py | 22 ++++++-------
- pyrpkg/utils.py    | 77 ++++++++++++++++++++++++++++++++++++++++------
- 2 files changed, 78 insertions(+), 21 deletions(-)
-
-diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py
-index b257fec..f562e71 100644
---- a/pyrpkg/__init__.py
-+++ b/pyrpkg/__init__.py
-@@ -53,7 +53,7 @@ from pyrpkg.sources import SourcesFile
- from pyrpkg.spec import SpecFile
- from pyrpkg.utils import (cached_property, extract_srpm, find_me,
-                           is_file_tracked, is_lookaside_eligible_file,
--                          log_result, spec_file_processed_by_rpmautospec)
-+                          log_result, spec_file_undo_rpmautospec)
- 
- from .gitignore import GitIgnore
- 
-@@ -1473,16 +1473,6 @@ class Commands(object):
-                     uploadfiles.append(file)
-                 else:
-                     files.append(file)
--
--                # Check all specfiles in SRPM. At this point (the 'import' command can run under
--                # the dist-git repo without any specfiles - right after initialization) we are
--                # not able determine which the main specfile is.
--                if file.endswith('.spec') and not file.startswith('.') \
--                        and not self.allow_pre_generated_srpm \
--                        and spec_file_processed_by_rpmautospec(file, target_dir):
--                    raise rpkgError('SRPM was processed by rpmautospec '
--                                    '(specfile "{}" was analyzed)'.format(file))
--
-         finally:
-             shutil.rmtree(target_dir)
- 
-@@ -2081,6 +2071,16 @@ class Commands(object):
-             os.chdir(oldpath)
-             raise rpkgError("Got an error from rpm2cpio: %s" % err)
- 
-+        # Undo rpmautospec from all the spec files.
-+        # At this point (the 'import' command can run under the dist-git repo
-+        # without any specfiles - right after initialization) we are
-+        # not able determine which the main specfile is.
-+        if not self.allow_pre_generated_srpm:
-+            for file in files:
-+                if file.endswith('.spec') and not file.startswith('.'):
-+                    if spec_file_undo_rpmautospec(file):
-+                        self.log.debug("rpmautospec processing removed from {0}".format(file))
-+
-         # And finally add all the files we know about (and our stock files)
-         for file in ('.gitignore', 'sources'):
-             if not os.path.exists(file):
-diff --git a/pyrpkg/utils.py b/pyrpkg/utils.py
-index 3337bdb..f3c8b25 100644
---- a/pyrpkg/utils.py
-+++ b/pyrpkg/utils.py
-@@ -336,22 +336,79 @@ def is_lookaside_eligible_file(file_name, dir_path=None):
-     return encoding == "binary"
- 
- 
--def spec_file_processed_by_rpmautospec(file_name, dir_path=None):
-+def _replace_lines(lines, startline, endline, replacement_lines=None, strip_endline=False):
-+    replacement_lines = replacement_lines or []
-+    try:
-+        start = lines.index(startline)
-+        end = lines.index(endline, start)
-+    except ValueError:
-+        # if both are missing, nothing to do, all good
-+        # if only one of them is present, we better not touch it
-+        return lines, False
-+    else:
-+        # rpmautospec adds an empty line after the end
-+        # we want to remove it, but only if it is actually empty
-+        if strip_endline and lines[end+1] == "\n":
-+            end += 1
-+        lines = lines[:start] + replacement_lines + lines[end+1:]
-+        return lines, True
-+
-+
-+def spec_file_undo_rpmautospec(file_name, dir_path=None):
-+    """
-+    Given a path to specfile, undo changes generated by rpmautospec.
-+    Iff there is something to undo, the specfile will be overwritten.
-+
-+    Namely:
-+
-+     1. Removes everything between the following lines:
-+          ## START: Set by rpmautospec
-+          ## END: Set by rpmautospec
-+     2. Replaces everything between the following lines with %autochangelog:
-+          ## START: Generated by rpmautospec
-+          ## END: Generated by rpmautospec
-+
-+    Both of the steps only happen once. If the specfile contains multiple such sections,
-+    only the first one is removed/replaced.
-+
-+    The saved spec file is not guaranteed to be bit-by-bit identical with the original
-+    spec file used as an input to rpmautospec.
-+    However, subsequent repeated conversions there and back should be quite stable.
-+
-+    The return value says whether the specfile was overwritten.
-+    """
-     file_path = os.path.join(dir_path or "", file_name)
- 
-     try:
--        contents = open(file_path).readlines()
-+        with open(file_path) as f:
-+            contents = f.readlines()
-     except Exception:
--        # if we can't read it, let's assume the answer is "no".
-+        # if we can't read it, let's do nothing
-         return False
- 
--    # Check for the %autorelease header prepended to the file
--    if any('START: Set by rpmautospec' in line for line in contents[:10]):
-+    # remove the generated macro section near the beginning of the specfile
-+    contents, was_removed = _replace_lines(
-+        contents,
-+        '## START: Set by rpmautospec\n',
-+        '## END: Set by rpmautospec\n',
-+        strip_endline=True)
-+
-+    # replace the generated changelog with %autochangelog
-+    # note that this does not generally produce content identical to the original
-+    # e.g. the macro could have been conditionalized or in curly brackets
-+    # most importantly, the %changelog section might have been omitted entirely
-+    # however, this should be Good Enough for most of us
-+    contents, was_replaced = _replace_lines(
-+        contents,
-+        '## START: Generated by rpmautospec\n',
-+        '## END: Generated by rpmautospec\n',
-+        ['%autochangelog\n'])
-+
-+    # finally, replace the spec if needed
-+    # if we cannot write it, better blow up
-+    if was_removed or was_replaced:
-+        with open(file_path, 'w') as f:
-+            f.writelines(contents)
-         return True
- 
--    # It seems that currently there's no mechanism to detect
--    # %autochangelog processing. But most packages would use both
--    # %autochangelog and %autorelease together, so we should catch
--    # most cases by checking for %autorelease only.
--    # https://pagure.io/fedora-infra/rpmautospec/issue/269
-     return False
--- 
-2.41.0
-

diff --git a/0031-Unittests-for-Undo-rpmautospec-processing.patch b/0031-Unittests-for-Undo-rpmautospec-processing.patch
deleted file mode 100644
index 571872c..0000000
--- a/0031-Unittests-for-Undo-rpmautospec-processing.patch
+++ /dev/null
@@ -1,258 +0,0 @@
-From 2bd726d20f3e5d1502a2191d0d263d0b6132982b Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Ond=C5=99ej=20Nosek?= <onosek@redhat.com>
-Date: Thu, 12 Oct 2023 01:40:36 +0200
-Subject: [PATCH 3/5] Unittests for "Undo rpmautospec processing"
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Merges: https://pagure.io/rpkg/pull-request/699
-Signed-off-by: Ondřej Nosek <onosek@redhat.com>
----
- Jenkinsfile                                   |  2 +-
- jenkins_test.dockerfile                       |  3 +-
- pyrpkg/utils.py                               |  6 +--
- tests/fixtures/docpkg/docpkg-rpmautospec.spec | 53 +++++++++++++++++++
- tests/test_cli.py                             | 40 +++++++-------
- tests/test_utils.py                           | 36 ++++++++++++-
- 6 files changed, 116 insertions(+), 24 deletions(-)
- create mode 100644 tests/fixtures/docpkg/docpkg-rpmautospec.spec
-
-diff --git a/pyrpkg/utils.py b/pyrpkg/utils.py
-index f3c8b25..fc01c7d 100644
---- a/pyrpkg/utils.py
-+++ b/pyrpkg/utils.py
-@@ -104,7 +104,7 @@ def log_result(log_func, result, level=0, indent=2):
-     elif isinstance(result, dict):
-         for key, value in result.items():
-             _log_value(log_func, key, level, indent, ':')
--            log_result(log_func, value, level+1)
-+            log_result(log_func, value, level + 1)
-     else:
-         _log_value(log_func, result, level, indent)
- 
-@@ -348,9 +348,9 @@ def _replace_lines(lines, startline, endline, replacement_lines=None, strip_endl
-     else:
-         # rpmautospec adds an empty line after the end
-         # we want to remove it, but only if it is actually empty
--        if strip_endline and lines[end+1] == "\n":
-+        if strip_endline and lines[end + 1] == "\n":
-             end += 1
--        lines = lines[:start] + replacement_lines + lines[end+1:]
-+        lines = lines[:start] + replacement_lines + lines[end + 1:]
-         return lines, True
- 
- 
-diff --git a/tests/fixtures/docpkg/docpkg-rpmautospec.spec b/tests/fixtures/docpkg/docpkg-rpmautospec.spec
-new file mode 100644
-index 0000000..5974b57
---- /dev/null
-+++ b/tests/fixtures/docpkg/docpkg-rpmautospec.spec
-@@ -0,0 +1,53 @@
-+## START: Set by rpmautospec
-+## (rpmautospec version 0.3.5)
-+## RPMAUTOSPEC: autorelease, autochangelog
-+%define autorelease(e:s:pb:n) %{?-p:0.}%{lua:
-+    release_number = 8;
-+    base_release_number = tonumber(rpm.expand("%{?-b*}%{!?-b:1}"));
-+    print(release_number + base_release_number - 1);
-+}%{?-e:.%{-e*}}%{?-s:.%{-s*}}%{!?-n:%{?dist}}
-+## END: Set by rpmautospec
-+
-+# autogenerated specfile
-+Summary: Dummy summary
-+Name: docpkg-rpmautospec
-+Version: 0.2
-+Release: 1%{dist}
-+License: GPL
-+Group: Applications/Productivity
-+
-+BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
-+Source0: hello-world.txt
-+Source1: docpkg.tar.gz
-+Source2: source-without-extension
-+# added empty dir just to test import srpm `fedpkg import`. It should skip the dir.
-+Source3: EMPTY_DIR
-+
-+%description
-+This is a dummy description.
-+
-+%prep
-+cp %{SOURCE0} .
-+
-+%build
-+
-+%clean
-+rm -rf $$RPM_BUILD_ROOT
-+%install
-+rm -rf $RPM_BUILD_ROOT
-+mkdir $RPM_BUILD_ROOT
-+mkdir -p $RPM_BUILD_ROOT/usr/share/doc
-+cp %{SOURCE0} $RPM_BUILD_ROOT/usr/share/doc/hello-world.txt
-+
-+%files
-+%doc "/usr/share/doc/hello-world.txt"
-+
-+%changelog
-+## START: Generated by rpmautospec
-+* Sun Jan  1 2006 tester <tester@example.com> - 0.2-1
-+- - New release 0.2-1
-+
-+* Sun Jan  1 2006 John Doe <jdoe@example.com> - 0.2-1
-+- Initial version
-+
-+## END: Generated by rpmautospec
-diff --git a/tests/test_cli.py b/tests/test_cli.py
-index f2e68df..3d90f36 100644
---- a/tests/test_cli.py
-+++ b/tests/test_cli.py
-@@ -1706,10 +1706,10 @@ class TestFailureImportSrpm(CliTestCase):
- class TestImportSrpm(LookasideCacheMock, CliTestCase):
- 
-     @staticmethod
--    def build_srpm(srcrpmdir):
-+    def build_srpm(srcrpmdir, specfile_name='docpkg.spec'):
-         """Build a fake SRPM used by this test case"""
-         docpkg_dir = os.path.join(fixtures_dir, 'docpkg')
--        specfile = os.path.join(docpkg_dir, 'docpkg.spec')
-+        specfile = os.path.join(docpkg_dir, specfile_name)
-         rpmbuild = [
-             'rpmbuild', '-bs',
-             '--define', '_topdir {0}'.format(srcrpmdir),
-@@ -1735,6 +1735,9 @@ class TestImportSrpm(LookasideCacheMock, CliTestCase):
- 
-         self.srcrpmdir = tempfile.mkdtemp(prefix='test-import-srpm-topdir-')
-         self.srpm_file = TestImportSrpm.build_srpm(self.srcrpmdir)
-+        self.srpm_file_rpmautospec = TestImportSrpm.build_srpm(
-+            self.srcrpmdir,
-+            specfile_name='docpkg-rpmautospec.spec')
- 
-         self.chaos_repo = tempfile.mkdtemp(prefix='rpkg-tests-chaos-repo-')
-         cmds = (
-@@ -1827,40 +1830,29 @@ class TestImportSrpm(LookasideCacheMock, CliTestCase):
-         self.assertFilesExist(['package.rpmlintrc'], search_dir=self.chaos_repo)
-         self.assertFilesNotExist(['the_file_is_not_in_reserved.yaml'], search_dir=self.chaos_repo)
- 
--    @patch('pyrpkg.spec_file_processed_by_rpmautospec')
--    def test_import_srpm_not_processed_by_rpmautospec(self, rpmautospec_processed):
-+    def test_import_srpm_not_processed_by_rpmautospec(self):
-         cli_cmd = ['rpkg', '--path', self.chaos_repo, '--name', 'docpkg',
-                    'import', '--skip-diffs', self.srpm_file]
- 
--        rpmautospec_processed.return_value = False
-         with patch('sys.argv', new=cli_cmd):
-             cli = self.new_cli()
-             with patch('pyrpkg.lookaside.CGILookasideCache.upload', self.lookasidecache_upload):
-                 cli.import_srpm()  # no exception should be raised
--            rpmautospec_processed.assert_called_once()
- 
--    @patch('pyrpkg.spec_file_processed_by_rpmautospec')
--    def test_import_srpm_processed_by_rpmautospec(self, rpmautospec_processed):
-+    def test_import_srpm_processed_by_rpmautospec(self):
-         cli_cmd = ['rpkg', '--path', self.chaos_repo, '--name', 'docpkg',
--                   'import', '--skip-diffs', self.srpm_file]
-+                   'import', '--skip-diffs', self.srpm_file_rpmautospec]
- 
--        rpmautospec_processed.return_value = True
-         with patch('sys.argv', new=cli_cmd):
-             cli = self.new_cli()
-             with patch('pyrpkg.lookaside.CGILookasideCache.upload', self.lookasidecache_upload):
--                six.assertRaisesRegex(
--                    self,
--                    rpkgError,
--                    'SRPM was processed by rpmautospec',
--                    cli.import_srpm)
--            rpmautospec_processed.assert_called_once()
-+                cli.import_srpm()
- 
--    @patch('pyrpkg.spec_file_processed_by_rpmautospec')
-+    @patch('pyrpkg.spec_file_undo_rpmautospec')
-     def test_import_srpm_processed_by_rpmautospec_allowed(self, rpmautospec_processed):
-         cli_cmd = ['rpkg', '--path', self.chaos_repo, '--name', 'docpkg',
-                    'import', '--skip-diffs', self.srpm_file]
- 
--        rpmautospec_processed.return_value = True
-         with patch('sys.argv', new=cli_cmd):
-             cli = self.new_cli()
-             cli.cmd.allow_pre_generated_srpm = True
-@@ -1868,6 +1860,18 @@ class TestImportSrpm(LookasideCacheMock, CliTestCase):
-                 cli.import_srpm()  # no exception should be raised
-             rpmautospec_processed.assert_not_called()
- 
-+    @patch('pyrpkg.spec_file_undo_rpmautospec')
-+    def test_import_srpm_processed_by_rpmautospec_not_allowed(self, rpmautospec_processed):
-+        cli_cmd = ['rpkg', '--path', self.chaos_repo, '--name', 'docpkg',
-+                   'import', '--skip-diffs', self.srpm_file]
-+
-+        with patch('sys.argv', new=cli_cmd):
-+            cli = self.new_cli()
-+            cli.cmd.allow_pre_generated_srpm = False  # or None
-+            with patch('pyrpkg.lookaside.CGILookasideCache.upload', self.lookasidecache_upload):
-+                cli.import_srpm()  # no exception should be raised
-+            rpmautospec_processed.assert_called_once()
-+
- 
- class TestMockbuild(CliTestCase):
-     """Test mockbuild command"""
-diff --git a/tests/test_utils.py b/tests/test_utils.py
-index 34188c5..0cd62d8 100644
---- a/tests/test_utils.py
-+++ b/tests/test_utils.py
-@@ -1,15 +1,22 @@
- import os
-+import shutil
- import tempfile
- import unittest
- import warnings
- 
-+try:
-+    import rpmautospec
-+except ImportError:
-+    rpmautospec = None
-+
- try:
-     from unittest import mock
- except ImportError:
-     import mock
- 
- from pyrpkg.utils import (cached_property, is_file_in_directory,
--                          is_file_tracked, log_result, warn_deprecated)
-+                          is_file_tracked, log_result,
-+                          spec_file_undo_rpmautospec, warn_deprecated)
- 
- from utils import CommandTestCase
- 
-@@ -287,3 +294,30 @@ class FileTrackedTestCase(CommandTestCase):
-                 self.repo_path
-             )
-         )
-+
-+
-+@unittest.skipIf(
-+    rpmautospec is None,
-+    "Skip test on releases where rpmautospec is not available (RHEL)")
-+class SpecFileUndoRpmautospec(CommandTestCase):
-+    def test_remove_autospec_from_specfile(self):
-+        fixtures_dir = os.path.join(os.path.dirname(__file__), "fixtures", "docpkg")
-+
-+        specfile_without_rpmautospec = os.path.join(fixtures_dir, "docpkg.spec")
-+        specfile_without_rpmautospec_copy = os.path.join(self.repo_path, "docpkg.spec")
-+        shutil.copy2(specfile_without_rpmautospec, specfile_without_rpmautospec_copy)
-+        self.assertFalse(rpmautospec.specfile_uses_rpmautospec(specfile_without_rpmautospec_copy))
-+        self.assertFalse(spec_file_undo_rpmautospec(specfile_without_rpmautospec_copy))
-+        self.assertFalse(rpmautospec.specfile_uses_rpmautospec(specfile_without_rpmautospec_copy))
-+        os.remove(specfile_without_rpmautospec_copy)
-+
-+        specfile_with_rpmautospec = os.path.join(fixtures_dir, "docpkg-rpmautospec.spec")
-+        specfile_with_rpmautospec_copy = os.path.join(self.repo_path, "docpkg-rpmautospec.spec")
-+        shutil.copy2(specfile_with_rpmautospec, specfile_with_rpmautospec_copy)
-+        # returns True if the specfile was modified
-+        self.assertTrue(spec_file_undo_rpmautospec(specfile_with_rpmautospec_copy))
-+        self.assertFalse(rpmautospec.specfile_uses_rpmautospec(
-+            specfile_with_rpmautospec_copy, check_autochangelog=False, check_autorelease=True))
-+        self.assertTrue(rpmautospec.specfile_uses_rpmautospec(
-+            specfile_with_rpmautospec_copy, check_autochangelog=True, check_autorelease=False))
-+        os.remove(specfile_with_rpmautospec_copy)
--- 
-2.41.0
-

diff --git a/0031-pkg-import-Undo-rpmautospec-processing.patch b/0031-pkg-import-Undo-rpmautospec-processing.patch
new file mode 100644
index 0000000..2d1f9e4
--- /dev/null
+++ b/0031-pkg-import-Undo-rpmautospec-processing.patch
@@ -0,0 +1,162 @@
+From ebb5c4b82caec5160544fdbb2d539fd1b5a3abfb Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= <miro@hroncok.cz>
+Date: Thu, 5 Oct 2023 16:59:22 +0200
+Subject: [PATCH 10/17] *pkg import: Undo rpmautospec processing
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Fixes https://pagure.io/fedpkg/issue/527
+
+Depends-on: https://pagure.io/fedora-infra/rpmautospec/pull-request/312
+
+Signed-off-by: Miro Hrončok <miro@hroncok.cz>
+---
+ pyrpkg/__init__.py | 22 ++++++-------
+ pyrpkg/utils.py    | 77 ++++++++++++++++++++++++++++++++++++++++------
+ 2 files changed, 78 insertions(+), 21 deletions(-)
+
+diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py
+index b257fec..f562e71 100644
+--- a/pyrpkg/__init__.py
++++ b/pyrpkg/__init__.py
+@@ -53,7 +53,7 @@ from pyrpkg.sources import SourcesFile
+ from pyrpkg.spec import SpecFile
+ from pyrpkg.utils import (cached_property, extract_srpm, find_me,
+                           is_file_tracked, is_lookaside_eligible_file,
+-                          log_result, spec_file_processed_by_rpmautospec)
++                          log_result, spec_file_undo_rpmautospec)
+ 
+ from .gitignore import GitIgnore
+ 
+@@ -1473,16 +1473,6 @@ class Commands(object):
+                     uploadfiles.append(file)
+                 else:
+                     files.append(file)
+-
+-                # Check all specfiles in SRPM. At this point (the 'import' command can run under
+-                # the dist-git repo without any specfiles - right after initialization) we are
+-                # not able determine which the main specfile is.
+-                if file.endswith('.spec') and not file.startswith('.') \
+-                        and not self.allow_pre_generated_srpm \
+-                        and spec_file_processed_by_rpmautospec(file, target_dir):
+-                    raise rpkgError('SRPM was processed by rpmautospec '
+-                                    '(specfile "{}" was analyzed)'.format(file))
+-
+         finally:
+             shutil.rmtree(target_dir)
+ 
+@@ -2081,6 +2071,16 @@ class Commands(object):
+             os.chdir(oldpath)
+             raise rpkgError("Got an error from rpm2cpio: %s" % err)
+ 
++        # Undo rpmautospec from all the spec files.
++        # At this point (the 'import' command can run under the dist-git repo
++        # without any specfiles - right after initialization) we are
++        # not able determine which the main specfile is.
++        if not self.allow_pre_generated_srpm:
++            for file in files:
++                if file.endswith('.spec') and not file.startswith('.'):
++                    if spec_file_undo_rpmautospec(file):
++                        self.log.debug("rpmautospec processing removed from {0}".format(file))
++
+         # And finally add all the files we know about (and our stock files)
+         for file in ('.gitignore', 'sources'):
+             if not os.path.exists(file):
+diff --git a/pyrpkg/utils.py b/pyrpkg/utils.py
+index 3337bdb..f3c8b25 100644
+--- a/pyrpkg/utils.py
++++ b/pyrpkg/utils.py
+@@ -336,22 +336,79 @@ def is_lookaside_eligible_file(file_name, dir_path=None):
+     return encoding == "binary"
+ 
+ 
+-def spec_file_processed_by_rpmautospec(file_name, dir_path=None):
++def _replace_lines(lines, startline, endline, replacement_lines=None, strip_endline=False):
++    replacement_lines = replacement_lines or []
++    try:
++        start = lines.index(startline)
++        end = lines.index(endline, start)
++    except ValueError:
++        # if both are missing, nothing to do, all good
++        # if only one of them is present, we better not touch it
++        return lines, False
++    else:
++        # rpmautospec adds an empty line after the end
++        # we want to remove it, but only if it is actually empty
++        if strip_endline and lines[end+1] == "\n":
++            end += 1
++        lines = lines[:start] + replacement_lines + lines[end+1:]
++        return lines, True
++
++
++def spec_file_undo_rpmautospec(file_name, dir_path=None):
++    """
++    Given a path to specfile, undo changes generated by rpmautospec.
++    Iff there is something to undo, the specfile will be overwritten.
++
++    Namely:
++
++     1. Removes everything between the following lines:
++          ## START: Set by rpmautospec
++          ## END: Set by rpmautospec
++     2. Replaces everything between the following lines with %autochangelog:
++          ## START: Generated by rpmautospec
++          ## END: Generated by rpmautospec
++
++    Both of the steps only happen once. If the specfile contains multiple such sections,
++    only the first one is removed/replaced.
++
++    The saved spec file is not guaranteed to be bit-by-bit identical with the original
++    spec file used as an input to rpmautospec.
++    However, subsequent repeated conversions there and back should be quite stable.
++
++    The return value says whether the specfile was overwritten.
++    """
+     file_path = os.path.join(dir_path or "", file_name)
+ 
+     try:
+-        contents = open(file_path).readlines()
++        with open(file_path) as f:
++            contents = f.readlines()
+     except Exception:
+-        # if we can't read it, let's assume the answer is "no".
++        # if we can't read it, let's do nothing
+         return False
+ 
+-    # Check for the %autorelease header prepended to the file
+-    if any('START: Set by rpmautospec' in line for line in contents[:10]):
++    # remove the generated macro section near the beginning of the specfile
++    contents, was_removed = _replace_lines(
++        contents,
++        '## START: Set by rpmautospec\n',
++        '## END: Set by rpmautospec\n',
++        strip_endline=True)
++
++    # replace the generated changelog with %autochangelog
++    # note that this does not generally produce content identical to the original
++    # e.g. the macro could have been conditionalized or in curly brackets
++    # most importantly, the %changelog section might have been omitted entirely
++    # however, this should be Good Enough for most of us
++    contents, was_replaced = _replace_lines(
++        contents,
++        '## START: Generated by rpmautospec\n',
++        '## END: Generated by rpmautospec\n',
++        ['%autochangelog\n'])
++
++    # finally, replace the spec if needed
++    # if we cannot write it, better blow up
++    if was_removed or was_replaced:
++        with open(file_path, 'w') as f:
++            f.writelines(contents)
+         return True
+ 
+-    # It seems that currently there's no mechanism to detect
+-    # %autochangelog processing. But most packages would use both
+-    # %autochangelog and %autorelease together, so we should catch
+-    # most cases by checking for %autorelease only.
+-    # https://pagure.io/fedora-infra/rpmautospec/issue/269
+     return False
+-- 
+2.43.0
+

diff --git a/0032-Unittests-for-Undo-rpmautospec-processing.patch b/0032-Unittests-for-Undo-rpmautospec-processing.patch
new file mode 100644
index 0000000..f806c1c
--- /dev/null
+++ b/0032-Unittests-for-Undo-rpmautospec-processing.patch
@@ -0,0 +1,289 @@
+From 2bd726d20f3e5d1502a2191d0d263d0b6132982b Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ond=C5=99ej=20Nosek?= <onosek@redhat.com>
+Date: Thu, 12 Oct 2023 01:40:36 +0200
+Subject: [PATCH] Unittests for "Undo rpmautospec processing"
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Merges: https://pagure.io/rpkg/pull-request/699
+Signed-off-by: Ondřej Nosek <onosek@redhat.com>
+---
+ Jenkinsfile                                   |  2 +-
+ jenkins_test.dockerfile                       |  3 +-
+ pyrpkg/utils.py                               |  6 +--
+ tests/fixtures/docpkg/docpkg-rpmautospec.spec | 53 +++++++++++++++++++
+ tests/test_cli.py                             | 40 +++++++-------
+ tests/test_utils.py                           | 36 ++++++++++++-
+ 6 files changed, 116 insertions(+), 24 deletions(-)
+ create mode 100644 tests/fixtures/docpkg/docpkg-rpmautospec.spec
+
+diff --git a/Jenkinsfile b/Jenkinsfile
+index 7b6742f..e6d6394 100644
+--- a/Jenkinsfile
++++ b/Jenkinsfile
+@@ -50,7 +50,7 @@ git fetch proposed
+ git checkout "origin/$params.BRANCH_TO"
+ git merge --no-ff "proposed/$params.BRANCH" -m "Merge PR"
+ 
+-podman run --rm -v .:/src:Z quay.io/exd-guild-source-tools/rpkg-test:latest tox -e py36,py39,flake8,bandit --workdir /tmp/tox ${TOX_POSARGS}
++podman run --rm -v .:/src:Z quay.io/exd-guild-source-tools/rpkg-test:latest tox -e py36,py39,py311,flake8,bandit --workdir /tmp/tox ${TOX_POSARGS}
+ # disabled py27 environment for now; keep just flake8 for Python 2
+ podman run --rm -v .:/src:Z quay.io/exd-guild-source-tools/rpkg-test-py2:latest tox -e flake8python2 --workdir /tmp/tox ${TOX_POSARGS}
+                         """
+diff --git a/jenkins_test.dockerfile b/jenkins_test.dockerfile
+index df8762e..d217a55 100644
+--- a/jenkins_test.dockerfile
++++ b/jenkins_test.dockerfile
+@@ -1,4 +1,4 @@
+-FROM fedora:37
++FROM fedora:38
+ LABEL \
+     name="rpkg test" \
+     description="Run tests using tox with Python 3" \
+@@ -9,6 +9,7 @@ RUN dnf -y update && dnf -y install \
+         python3-devel \
+         python3-openidc-client \
+         python3-libmodulemd \
++        python3-rpmautospec \
+         python3-setuptools \
+         rpmlint \
+         rpm-build \
+diff --git a/pyrpkg/utils.py b/pyrpkg/utils.py
+index f3c8b25..fc01c7d 100644
+--- a/pyrpkg/utils.py
++++ b/pyrpkg/utils.py
+@@ -104,7 +104,7 @@ def log_result(log_func, result, level=0, indent=2):
+     elif isinstance(result, dict):
+         for key, value in result.items():
+             _log_value(log_func, key, level, indent, ':')
+-            log_result(log_func, value, level+1)
++            log_result(log_func, value, level + 1)
+     else:
+         _log_value(log_func, result, level, indent)
+ 
+@@ -348,9 +348,9 @@ def _replace_lines(lines, startline, endline, replacement_lines=None, strip_endl
+     else:
+         # rpmautospec adds an empty line after the end
+         # we want to remove it, but only if it is actually empty
+-        if strip_endline and lines[end+1] == "\n":
++        if strip_endline and lines[end + 1] == "\n":
+             end += 1
+-        lines = lines[:start] + replacement_lines + lines[end+1:]
++        lines = lines[:start] + replacement_lines + lines[end + 1:]
+         return lines, True
+ 
+ 
+diff --git a/tests/fixtures/docpkg/docpkg-rpmautospec.spec b/tests/fixtures/docpkg/docpkg-rpmautospec.spec
+new file mode 100644
+index 0000000..5974b57
+--- /dev/null
++++ b/tests/fixtures/docpkg/docpkg-rpmautospec.spec
+@@ -0,0 +1,53 @@
++## START: Set by rpmautospec
++## (rpmautospec version 0.3.5)
++## RPMAUTOSPEC: autorelease, autochangelog
++%define autorelease(e:s:pb:n) %{?-p:0.}%{lua:
++    release_number = 8;
++    base_release_number = tonumber(rpm.expand("%{?-b*}%{!?-b:1}"));
++    print(release_number + base_release_number - 1);
++}%{?-e:.%{-e*}}%{?-s:.%{-s*}}%{!?-n:%{?dist}}
++## END: Set by rpmautospec
++
++# autogenerated specfile
++Summary: Dummy summary
++Name: docpkg-rpmautospec
++Version: 0.2
++Release: 1%{dist}
++License: GPL
++Group: Applications/Productivity
++
++BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
++Source0: hello-world.txt
++Source1: docpkg.tar.gz
++Source2: source-without-extension
++# added empty dir just to test import srpm `fedpkg import`. It should skip the dir.
++Source3: EMPTY_DIR
++
++%description
++This is a dummy description.
++
++%prep
++cp %{SOURCE0} .
++
++%build
++
++%clean
++rm -rf $$RPM_BUILD_ROOT
++%install
++rm -rf $RPM_BUILD_ROOT
++mkdir $RPM_BUILD_ROOT
++mkdir -p $RPM_BUILD_ROOT/usr/share/doc
++cp %{SOURCE0} $RPM_BUILD_ROOT/usr/share/doc/hello-world.txt
++
++%files
++%doc "/usr/share/doc/hello-world.txt"
++
++%changelog
++## START: Generated by rpmautospec
++* Sun Jan  1 2006 tester <tester@example.com> - 0.2-1
++- - New release 0.2-1
++
++* Sun Jan  1 2006 John Doe <jdoe@example.com> - 0.2-1
++- Initial version
++
++## END: Generated by rpmautospec
+diff --git a/tests/test_cli.py b/tests/test_cli.py
+index f2e68df..3d90f36 100644
+--- a/tests/test_cli.py
++++ b/tests/test_cli.py
+@@ -1706,10 +1706,10 @@ class TestFailureImportSrpm(CliTestCase):
+ class TestImportSrpm(LookasideCacheMock, CliTestCase):
+ 
+     @staticmethod
+-    def build_srpm(srcrpmdir):
++    def build_srpm(srcrpmdir, specfile_name='docpkg.spec'):
+         """Build a fake SRPM used by this test case"""
+         docpkg_dir = os.path.join(fixtures_dir, 'docpkg')
+-        specfile = os.path.join(docpkg_dir, 'docpkg.spec')
++        specfile = os.path.join(docpkg_dir, specfile_name)
+         rpmbuild = [
+             'rpmbuild', '-bs',
+             '--define', '_topdir {0}'.format(srcrpmdir),
+@@ -1735,6 +1735,9 @@ class TestImportSrpm(LookasideCacheMock, CliTestCase):
+ 
+         self.srcrpmdir = tempfile.mkdtemp(prefix='test-import-srpm-topdir-')
+         self.srpm_file = TestImportSrpm.build_srpm(self.srcrpmdir)
++        self.srpm_file_rpmautospec = TestImportSrpm.build_srpm(
++            self.srcrpmdir,
++            specfile_name='docpkg-rpmautospec.spec')
+ 
+         self.chaos_repo = tempfile.mkdtemp(prefix='rpkg-tests-chaos-repo-')
+         cmds = (
+@@ -1827,40 +1830,29 @@ class TestImportSrpm(LookasideCacheMock, CliTestCase):
+         self.assertFilesExist(['package.rpmlintrc'], search_dir=self.chaos_repo)
+         self.assertFilesNotExist(['the_file_is_not_in_reserved.yaml'], search_dir=self.chaos_repo)
+ 
+-    @patch('pyrpkg.spec_file_processed_by_rpmautospec')
+-    def test_import_srpm_not_processed_by_rpmautospec(self, rpmautospec_processed):
++    def test_import_srpm_not_processed_by_rpmautospec(self):
+         cli_cmd = ['rpkg', '--path', self.chaos_repo, '--name', 'docpkg',
+                    'import', '--skip-diffs', self.srpm_file]
+ 
+-        rpmautospec_processed.return_value = False
+         with patch('sys.argv', new=cli_cmd):
+             cli = self.new_cli()
+             with patch('pyrpkg.lookaside.CGILookasideCache.upload', self.lookasidecache_upload):
+                 cli.import_srpm()  # no exception should be raised
+-            rpmautospec_processed.assert_called_once()
+ 
+-    @patch('pyrpkg.spec_file_processed_by_rpmautospec')
+-    def test_import_srpm_processed_by_rpmautospec(self, rpmautospec_processed):
++    def test_import_srpm_processed_by_rpmautospec(self):
+         cli_cmd = ['rpkg', '--path', self.chaos_repo, '--name', 'docpkg',
+-                   'import', '--skip-diffs', self.srpm_file]
++                   'import', '--skip-diffs', self.srpm_file_rpmautospec]
+ 
+-        rpmautospec_processed.return_value = True
+         with patch('sys.argv', new=cli_cmd):
+             cli = self.new_cli()
+             with patch('pyrpkg.lookaside.CGILookasideCache.upload', self.lookasidecache_upload):
+-                six.assertRaisesRegex(
+-                    self,
+-                    rpkgError,
+-                    'SRPM was processed by rpmautospec',
+-                    cli.import_srpm)
+-            rpmautospec_processed.assert_called_once()
++                cli.import_srpm()
+ 
+-    @patch('pyrpkg.spec_file_processed_by_rpmautospec')
++    @patch('pyrpkg.spec_file_undo_rpmautospec')
+     def test_import_srpm_processed_by_rpmautospec_allowed(self, rpmautospec_processed):
+         cli_cmd = ['rpkg', '--path', self.chaos_repo, '--name', 'docpkg',
+                    'import', '--skip-diffs', self.srpm_file]
+ 
+-        rpmautospec_processed.return_value = True
+         with patch('sys.argv', new=cli_cmd):
+             cli = self.new_cli()
+             cli.cmd.allow_pre_generated_srpm = True
+@@ -1868,6 +1860,18 @@ class TestImportSrpm(LookasideCacheMock, CliTestCase):
+                 cli.import_srpm()  # no exception should be raised
+             rpmautospec_processed.assert_not_called()
+ 
++    @patch('pyrpkg.spec_file_undo_rpmautospec')
++    def test_import_srpm_processed_by_rpmautospec_not_allowed(self, rpmautospec_processed):
++        cli_cmd = ['rpkg', '--path', self.chaos_repo, '--name', 'docpkg',
++                   'import', '--skip-diffs', self.srpm_file]
++
++        with patch('sys.argv', new=cli_cmd):
++            cli = self.new_cli()
++            cli.cmd.allow_pre_generated_srpm = False  # or None
++            with patch('pyrpkg.lookaside.CGILookasideCache.upload', self.lookasidecache_upload):
++                cli.import_srpm()  # no exception should be raised
++            rpmautospec_processed.assert_called_once()
++
+ 
+ class TestMockbuild(CliTestCase):
+     """Test mockbuild command"""
+diff --git a/tests/test_utils.py b/tests/test_utils.py
+index 34188c5..0cd62d8 100644
+--- a/tests/test_utils.py
++++ b/tests/test_utils.py
+@@ -1,15 +1,22 @@
+ import os
++import shutil
+ import tempfile
+ import unittest
+ import warnings
+ 
++try:
++    import rpmautospec
++except ImportError:
++    rpmautospec = None
++
+ try:
+     from unittest import mock
+ except ImportError:
+     import mock
+ 
+ from pyrpkg.utils import (cached_property, is_file_in_directory,
+-                          is_file_tracked, log_result, warn_deprecated)
++                          is_file_tracked, log_result,
++                          spec_file_undo_rpmautospec, warn_deprecated)
+ 
+ from utils import CommandTestCase
+ 
+@@ -287,3 +294,30 @@ class FileTrackedTestCase(CommandTestCase):
+                 self.repo_path
+             )
+         )
++
++
++@unittest.skipIf(
++    rpmautospec is None,
++    "Skip test on releases where rpmautospec is not available (RHEL)")
++class SpecFileUndoRpmautospec(CommandTestCase):
++    def test_remove_autospec_from_specfile(self):
++        fixtures_dir = os.path.join(os.path.dirname(__file__), "fixtures", "docpkg")
++
++        specfile_without_rpmautospec = os.path.join(fixtures_dir, "docpkg.spec")
++        specfile_without_rpmautospec_copy = os.path.join(self.repo_path, "docpkg.spec")
++        shutil.copy2(specfile_without_rpmautospec, specfile_without_rpmautospec_copy)
++        self.assertFalse(rpmautospec.specfile_uses_rpmautospec(specfile_without_rpmautospec_copy))
++        self.assertFalse(spec_file_undo_rpmautospec(specfile_without_rpmautospec_copy))
++        self.assertFalse(rpmautospec.specfile_uses_rpmautospec(specfile_without_rpmautospec_copy))
++        os.remove(specfile_without_rpmautospec_copy)
++
++        specfile_with_rpmautospec = os.path.join(fixtures_dir, "docpkg-rpmautospec.spec")
++        specfile_with_rpmautospec_copy = os.path.join(self.repo_path, "docpkg-rpmautospec.spec")
++        shutil.copy2(specfile_with_rpmautospec, specfile_with_rpmautospec_copy)
++        # returns True if the specfile was modified
++        self.assertTrue(spec_file_undo_rpmautospec(specfile_with_rpmautospec_copy))
++        self.assertFalse(rpmautospec.specfile_uses_rpmautospec(
++            specfile_with_rpmautospec_copy, check_autochangelog=False, check_autorelease=True))
++        self.assertTrue(rpmautospec.specfile_uses_rpmautospec(
++            specfile_with_rpmautospec_copy, check_autochangelog=True, check_autorelease=False))
++        os.remove(specfile_with_rpmautospec_copy)
+-- 
+2.43.0
+

diff --git a/0033-Update-docker-image-for-Jenkinks-tests.patch b/0033-Update-docker-image-for-Jenkinks-tests.patch
new file mode 100644
index 0000000..06d747d
--- /dev/null
+++ b/0033-Update-docker-image-for-Jenkinks-tests.patch
@@ -0,0 +1,73 @@
+From 898b2c61506e72847bae00aa8ffe228aebb69547 Mon Sep 17 00:00:00 2001
+From: Ondrej Nosek <onosek@redhat.com>
+Date: Tue, 7 Mar 2023 19:15:28 +0100
+Subject: [PATCH] Update docker image for Jenkinks tests
+
+Regenerate the docker image: Fedora 35 --> Fedora 37.
+Jenkinsfile as a pipeline script is unified with fedpkg.
+
+JIRA: RHELCMP-11391
+Signed-off-by: Ondrej Nosek <onosek@redhat.com>
+---
+ Jenkinsfile             | 14 +++++++++-----
+ jenkins_test.dockerfile |  2 +-
+ 2 files changed, 10 insertions(+), 6 deletions(-)
+
+diff --git a/Jenkinsfile b/Jenkinsfile
+index b67b9a7..7b6742f 100644
+--- a/Jenkinsfile
++++ b/Jenkinsfile
+@@ -23,7 +23,7 @@ pipeline {
+                     }
+                     try {
+                         echo "Requesting duffy node ..."
+-                        def session_str = sh returnStdout: true, script: "set +x; duffy client --url https://duffy.ci.centos.org/api/v1 --auth-name fedora-infra --auth-key $CICO_API_KEY request-session pool=virt-ec2-t2-centos-9s-x86_64,quantity=1"
++                        def session_str = sh returnStdout: true, script: "set +x; duffy client --url https://duffy.ci.centos.org/api/v1 --auth-name fedora-infra --auth-key $CICO_API_KEY request-session pool=virt-ec2-t2-centos-8s-x86_64,quantity=1"
+                         def session = readJSON text: session_str
+                         DUFFY_SESSION_ID= session.session.id
+                         def hostname = session.session.nodes[0].hostname
+@@ -31,7 +31,7 @@ pipeline {
+                         def remote_dir = "/tmp/$JENKINS_AGENT_NAME"
+                         echo "remote_dir: $remote_dir"
+                         // this makes tests run in parallel if needed: "--parallel=auto --parallel-live"
+-                        def TOX_POSARGS =
++                        def TOX_POSARGS = ""
+                         writeFile file: 'job.sh', text: """
+ set -xe
+ dnf install -y git podman
+@@ -40,15 +40,19 @@ git config --global user.name "jenkins"
+ cd $remote_dir
+ git clone https://pagure.io/rpkg.git -b master
+ cd rpkg
+-git remote rm proposed || true
++# remove remote only if exists
++remotes=\$(git remote)
++if echo "\$remotes" | grep -q "^proposed\$"; then
++  git remote rm proposed || true
++fi
+ git remote add proposed "$params.REPO"
+ git fetch proposed
+ git checkout "origin/$params.BRANCH_TO"
+ git merge --no-ff "proposed/$params.BRANCH" -m "Merge PR"
+ 
+-podman run --rm -v .:/src:Z quay.io/exd-guild-source-tools/rpkg-test tox -e py36,py39,flake8,bandit --workdir /tmp/tox ${TOX_POSARGS}
++podman run --rm -v .:/src:Z quay.io/exd-guild-source-tools/rpkg-test:latest tox -e py36,py39,flake8,bandit --workdir /tmp/tox ${TOX_POSARGS}
+ # disabled py27 environment for now; keep just flake8 for Python 2
+-podman run --rm -v .:/src:Z quay.io/exd-guild-source-tools/rpkg-test-py2 tox -e flake8python2 --workdir /tmp/tox ${TOX_POSARGS}
++podman run --rm -v .:/src:Z quay.io/exd-guild-source-tools/rpkg-test-py2:latest tox -e flake8python2 --workdir /tmp/tox ${TOX_POSARGS}
+                         """
+                         sh "cat job.sh"
+                         sh "ssh -o StrictHostKeyChecking=no root@$hostname mkdir $remote_dir"
+diff --git a/jenkins_test.dockerfile b/jenkins_test.dockerfile
+index 43245b1..df8762e 100644
+--- a/jenkins_test.dockerfile
++++ b/jenkins_test.dockerfile
+@@ -1,4 +1,4 @@
+-FROM fedora:35
++FROM fedora:37
+ LABEL \
+     name="rpkg test" \
+     description="Run tests using tox with Python 3" \
+-- 
+2.43.0
+

diff --git a/0034-mockbuild-new-argument-extra-pkgs.patch b/0034-mockbuild-new-argument-extra-pkgs.patch
new file mode 100644
index 0000000..9579dd3
--- /dev/null
+++ b/0034-mockbuild-new-argument-extra-pkgs.patch
@@ -0,0 +1,68 @@
+From 89d3bb0d34250fe24eed5bc63edd992e932a622a Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ond=C5=99ej=20Nosek?= <onosek@redhat.com>
+Date: Wed, 15 Nov 2023 02:53:10 +0100
+Subject: [PATCH 14/17] `mockbuild`: new argument --extra-pkgs
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Added the new argument `--extra-pkgs` to `mockbuild` command.
+It installs additional packages to mock's chroot. In some cases is
+possible to use the current mechanism of extra args placed
+after `--` at the end of the command line instead of `--extra-pkgs`.
+
+  Example: fedpkg mockbuild -- --additional-package <pkg>
+
+Argument(s) `additional-package` is passed to `mock`.
+`additional-package` can't be used together with `--shell`.
+
+JIRA: RHELCMP-11017
+Fixes: https://pagure.io/fedpkg/issue/498
+
+Signed-off-by: Ondřej Nosek <onosek@redhat.com>
+---
+ pyrpkg/cli.py | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+diff --git a/pyrpkg/cli.py b/pyrpkg/cli.py
+index 6fd6df0..06f4c1a 100644
+--- a/pyrpkg/cli.py
++++ b/pyrpkg/cli.py
+@@ -1152,6 +1152,9 @@ class cliClient(object):
+             '--use-local-mock-config', default=None, dest="local_mock_config",
+             action='store_true',
+             help="Enforce use of local Mock configuration.")
++        mockbuild_parser.add_argument(
++            '--extra-pkgs', action='append', nargs='*',
++            help="Install additional packages into chroot")
+ 
+         mockbuild_parser.set_defaults(command=self.mockbuild)
+ 
+@@ -2514,6 +2517,24 @@ class cliClient(object):
+                                                  "%s-%s-%s.src.rpm"
+                                                  % (self.cmd.repo_name, self.cmd.ver, self.cmd.rel))
+                 self.log.debug('Srpm generated: {0}'.format(self.cmd.srpmname))
++            if self.args.extra_pkgs:
++                mockargs_extra_pkgs = []
++                list_extra_pkgs = []
++                # process possible multiple argument's occurrences
++                for arg_arr in self.args.extra_pkgs:
++                    for additional_package in arg_arr:
++                        mockargs_extra_pkgs.extend(['--additional-package', additional_package])
++                        list_extra_pkgs.append(additional_package)
++                # installation will run in separated mock process, so do not clean prepared chroot
++                # before the main mock run
++                mockargs_extra_pkgs.extend(['--no-cleanup-after'])
++                self.log.info('Installing extra packages into the mock chroot: {}'.format(
++                    ', '.join(list_extra_pkgs)))
++                self.cmd.mockbuild(mockargs_extra_pkgs, self.args.root,
++                                   hashtype=self.args.hash,
++                                   shell=None,  # nosec
++                                   force_local_mock_config=self.args.local_mock_config)
++
+             self.cmd.mockbuild(mockargs, self.args.root,
+                                hashtype=self.args.hash,
+                                shell=self.args.shell,  # nosec
+-- 
+2.43.0
+

diff --git a/0035-Add-option-to-mockbuild-use-default-resultdir-of-moc.patch b/0035-Add-option-to-mockbuild-use-default-resultdir-of-moc.patch
new file mode 100644
index 0000000..9f8f4a0
--- /dev/null
+++ b/0035-Add-option-to-mockbuild-use-default-resultdir-of-moc.patch
@@ -0,0 +1,69 @@
+From 446b80ad746771dbfa938476504e13c829f2e7f6 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?S=C3=A9rgio=20M=2E=20Basto?= <sergio@serjux.com>
+Date: Mon, 3 Oct 2022 01:11:20 +0100
+Subject: [PATCH 17/17] Add option to mockbuild use default resultdir of mock
+ (v3)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Merges: https://pagure.io/rpkg/pull-request/637
+
+Signed-off-by: Sérgio M. Basto <sergio@serjux.com>
+---
+ pyrpkg/__init__.py | 6 ++++--
+ pyrpkg/cli.py      | 7 ++++++-
+ 2 files changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py
+index d2d8c8a..4c56169 100644
+--- a/pyrpkg/__init__.py
++++ b/pyrpkg/__init__.py
+@@ -3127,7 +3127,7 @@ class Commands(object):
+         return root, config_dir
+ 
+     def mockbuild(self, mockargs=[], root=None, hashtype=None, shell=None,
+-                  force_local_mock_config=None, srpm_mock=False):
++                  force_local_mock_config=None, srpm_mock=False, default_mock_resultdir=False):
+         """Build the package in mock, using mockargs
+ 
+         Log the output and returns nothing
+@@ -3167,7 +3167,9 @@ class Commands(object):
+         if config_dir:
+             cmd.extend(['--configdir', config_dir])
+ 
+-        cmd += ['-r', root, '--resultdir', self.mock_results_dir]
++        cmd += ['-r', root]
++        if default_mock_resultdir is not True:
++            cmd += ['--resultdir', self.mock_results_dir]
+ 
+         if shell:
+             cmd.append('--shell')
+diff --git a/pyrpkg/cli.py b/pyrpkg/cli.py
+index b6adaad..621df32 100644
+--- a/pyrpkg/cli.py
++++ b/pyrpkg/cli.py
+@@ -1154,6 +1154,10 @@ class cliClient(object):
+             '--use-local-mock-config', default=None, dest="local_mock_config",
+             action='store_true',
+             help="Enforce use of local Mock configuration.")
++        mockbuild_parser.add_argument(
++            '--default-mock-resultdir', default=None, dest="default_mock_resultdir",
++            action='store_true',
++            help="Don't modify Mock resultdir.")
+         mockbuild_parser.add_argument(
+             '--extra-pkgs', action='append', nargs='*',
+             help="Install additional packages into chroot")
+@@ -2544,7 +2548,8 @@ class cliClient(object):
+             self.cmd.mockbuild(mockargs, self.args.root,
+                                hashtype=self.args.hash,
+                                shell=self.args.shell,  # nosec
+-                               force_local_mock_config=self.args.local_mock_config)
++                               force_local_mock_config=self.args.local_mock_config,
++                               default_mock_resultdir=self.args.default_mock_resultdir)
+         except Exception as e:
+             raise rpkgError(e)
+ 
+-- 
+2.43.0
+

diff --git a/rpkg.spec b/rpkg.spec
index 4cdffff..5f213de 100644
--- a/rpkg.spec
+++ b/rpkg.spec
@@ -1,6 +1,6 @@
 Name:           rpkg
 Version:        1.66
-Release:        14%{?dist}
+Release:        15%{?dist}
 
 Summary:        Python library for interacting with rpm+git
 License:        GPLv2+ and LGPLv2
@@ -39,32 +39,36 @@ Patch3:         0003-Remove-Environment-Markers-syntax.patch
 %endif
 Patch4:         0004-Process-source-URLs-with-fragment-in-pre-push-hook.patch
 Patch5:         0005-container-build-update-signing-intent-help-for-OSBS-.patch
-Patch6:         0006-Do-not-generate-pre-push-hook-script-in-some-cases.patch
-Patch7:         0007-More-robust-spec-file-presence-checking.patch
-Patch8:         0008-Update-to-spec-file-presence-checking.patch
-Patch9:         0009-Add-more-information-about-pre-push-hook.patch
-Patch10:        0010-pre-push-check-have-to-use-spectool-with-define.patch
-Patch11:        0011-A-HEAD-query-into-a-lookaside-cache.patch
-Patch12:        0012-pre-push-hook-script-contains-a-user-s-config.patch
-Patch13:        0013-Fix-unittests-for-clone-and-pre-push-hook-script.patch
-Patch14:        0014-import_srpm-allow-pre-generated-srpms.patch
-Patch15:        0015-Ignore-missing-spec-file-in-pre-push-hook.patch
-Patch16:        0016-Check-remote-file-with-correct-hash.patch
-Patch17:        0017-Allow-empty-commits-when-uses_rpmautospec.patch
-Patch18:        0018-Config-file-option-to-skip-the-hook-script-creation.patch
-Patch19:        0019-Pre-push-hook-won-t-check-private-branches.patch
-Patch20:        0020-Use-release-s-rpmdefines-in-unused-sources-check.patch
-Patch21:        0021-Do-not-require-sources-file-for-all-namespaces.patch
-Patch22:        0022-commit-command-fails-on-containers-namespace.patch
-Patch23:        0023-Split-git-credential-data-on-first-only.patch
-Patch24:        0024-Support-for-checking-exploded-sources-before-push.patch
-Patch25:        0025-Fix-flake8-complaints.patch
-Patch26:        0026-Prepare-the-lookaside-cache-code-for-retries.patch
-Patch27:        0027-Lookaside-cache-operations-retries.patch
-Patch28:        0028-Make-lookaside-cache-retries-configurable.patch
-Patch29:        0029-pkg-import-Don-t-delete-changelog-generated-by-rpmau.patch
-Patch30:        0030-pkg-import-Undo-rpmautospec-processing.patch
-Patch31:        0031-Unittests-for-Undo-rpmautospec-processing.patch
+Patch6:         0033-Update-docker-image-for-Jenkinks-tests.patch
+Patch7:         0006-Do-not-generate-pre-push-hook-script-in-some-cases.patch
+Patch8:         0007-More-robust-spec-file-presence-checking.patch
+Patch9:         0008-Update-to-spec-file-presence-checking.patch
+Patch10:        0009-Add-more-information-about-pre-push-hook.patch
+Patch11:        0010-pre-push-check-have-to-use-spectool-with-define.patch
+Patch12:        0011-A-HEAD-query-into-a-lookaside-cache.patch
+Patch13:        0012-pre-push-hook-script-contains-a-user-s-config.patch
+Patch14:        0013-Fix-unittests-for-clone-and-pre-push-hook-script.patch
+Patch15:        0014-import_srpm-allow-pre-generated-srpms.patch
+Patch16:        0015-Ignore-missing-spec-file-in-pre-push-hook.patch
+Patch17:        0016-Check-remote-file-with-correct-hash.patch
+Patch18:        0017-Allow-empty-commits-when-uses_rpmautospec.patch
+Patch19:        0018-Config-file-option-to-skip-the-hook-script-creation.patch
+Patch20:        0019-Pre-push-hook-won-t-check-private-branches.patch
+Patch21:        0020-Use-release-s-rpmdefines-in-unused-sources-check.patch
+Patch22:        0021-Do-not-require-sources-file-for-all-namespaces.patch
+Patch23:        0022-copr-build-passes-extra_args-to-copr-cli-command.patch
+Patch24:        0023-commit-command-fails-on-containers-namespace.patch
+Patch25:        0024-Split-git-credential-data-on-first-only.patch
+Patch26:        0025-Support-for-checking-exploded-sources-before-push.patch
+Patch27:        0026-Fix-flake8-complaints.patch
+Patch28:        0027-Prepare-the-lookaside-cache-code-for-retries.patch
+Patch29:        0028-Lookaside-cache-operations-retries.patch
+Patch30:        0029-Make-lookaside-cache-retries-configurable.patch
+Patch31:        0030-pkg-import-Don-t-delete-changelog-generated-by-rpmau.patch
+Patch32:        0031-pkg-import-Undo-rpmautospec-processing.patch
+Patch33:        0032-Unittests-for-Undo-rpmautospec-processing.patch
+Patch34:        0034-mockbuild-new-argument-extra-pkgs.patch
+Patch35:        0035-Add-option-to-mockbuild-use-default-resultdir-of-moc.patch
 
 %description
 Python library for interacting with rpm+git
@@ -281,6 +285,11 @@ example_cli_dir=$RPM_BUILD_ROOT%{_datadir}/%{name}/examples/cli
 
 
 %changelog
+* Wed Jan 10 2024 Ondřej Nosek <onosek@redhat.com> - 1.66-15
+- Patch: Add option to mockbuild use default resultdir of mock (v3)
+- Patch: mockbuild`: new argument --extra-pkgs
+- Patch: `copr-build` passes extra_args to copr-cli command
+
 * Mon Dec 11 2023 Miro Hrončok <mhroncok@redhat.com> - 1.66-14
 - Actually add the patches:
 - Patch: *pkg import: Don't delete changelog generated by `rpmautospec convert`

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [rpms/rpkg] 1.70-1: A few patches:
@ 2026-08-10 21:44 
  0 siblings, 0 replies; 6+ messages in thread
From:  @ 2026-08-10 21:44 UTC (permalink / raw)
  To: git-commits

            A new commit has been pushed.

            Repo   : rpms/rpkg
            Branch : 1.70-1
            Commit : f8a7f14fbe3c2bd3229a3e023cf78e090f39dde6
            Author : Ondřej Nosek <onosek@redhat.com>
            Date   : 2025-09-03T00:29:53+00:00
            Stats  : +309/-5 in 7 file(s)
            URL    : https://src.fedoraproject.org/rpms/rpkg/c/f8a7f14fbe3c2bd3229a3e023cf78e090f39dde6?branch=1.70-1

            Log:
            A few patches:

- Patch: `pre-push-check`: bogus error - file wasn't listed
- Patch: Fix mockbuild --srpm-mock specfile_path
- Patch: `patch`: Execute subprocess in text mode
- Patch: type: fix typo in requirements README.
- Patch: `install`: add rpmbuild arguments `--with` and `--without`
- Patch: `srpm`: man page generation fixed

Signed-off-by: Ondřej Nosek <onosek@redhat.com>

---
diff --git a/0002-pre-push-check-bogus-error-file-wasn-t-listed.patch b/0002-pre-push-check-bogus-error-file-wasn-t-listed.patch
new file mode 100644
index 0000000..cca0e36
--- /dev/null
+++ b/0002-pre-push-check-bogus-error-file-wasn-t-listed.patch
@@ -0,0 +1,39 @@
+From 3e766e09ab5403f01c92bb57f0bf4b7ed5cb8b10 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ond=C5=99ej=20Nosek?= <onosek@redhat.com>
+Date: Tue, 8 Jul 2025 16:49:57 +0200
+Subject: [PATCH 08/13] `pre-push-check`: bogus error - file wasn't listed
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+During the check before a push operation, a file was falsely marked
+as not listed in the specfile and the check failed.
+The marked patch was named "./0001-some-fix.patch" which is rarely
+seen in the specfile. As a fix, file names are normalized and thus
+'./' prefix is removed.
+
+Fixes: #747
+JIRA: RHELCMP-14651
+
+Signed-off-by: Ondřej Nosek <onosek@redhat.com>
+---
+ pyrpkg/__init__.py | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py
+index bf8c3e2..8b2ec89 100644
+--- a/pyrpkg/__init__.py
++++ b/pyrpkg/__init__.py
+@@ -4617,7 +4617,8 @@ class Commands(object):
+                 elif res.scheme and res.netloc:
+                     source_files.append(os.path.basename(res.path))
+                 else:
+-                    source_files.append(file_location)
++                    # file path could rarely be in format './0001-my-fix.patch' - normalize it
++                    source_files.append(os.path.normpath(file_location))
+ 
+         if not len(source_files):
+             self.log.warning('No source files found in the specfile \'{0}\'. '
+-- 
+2.51.0
+

diff --git a/0003-Fix-mockbuild-srpm-mock-specfile_path.patch b/0003-Fix-mockbuild-srpm-mock-specfile_path.patch
new file mode 100644
index 0000000..db8fb72
--- /dev/null
+++ b/0003-Fix-mockbuild-srpm-mock-specfile_path.patch
@@ -0,0 +1,27 @@
+From 266ce739a075c6cee1a0221fd8faf0fc823daf37 Mon Sep 17 00:00:00 2001
+From: Tony Wang <wngtk@outlook.com>
+Date: Wed, 2 Jul 2025 21:51:01 +0800
+Subject: [PATCH 09/13] Fix mockbuild --srpm-mock specfile_path
+
+Signed-off-by: Tony Wang <wngtk@outlook.com>
+---
+ pyrpkg/__init__.py | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py
+index 8b2ec89..ad5ee31 100644
+--- a/pyrpkg/__init__.py
++++ b/pyrpkg/__init__.py
+@@ -3207,7 +3207,8 @@ class Commands(object):
+         if shell:
+             cmd.append('--shell')
+         elif srpm_mock:
+-            cmd += ['--buildsrpm', '--sources', self.layout.sourcedir, '--spec', self.spec]
++            specfile_path = os.path.join(self.layout.specdir, self.spec)
++            cmd += ['--buildsrpm', '--sources', self.layout.sourcedir, '--spec', specfile_path]
+         else:
+             cmd += ['--rebuild', self.srpmname]
+ 
+-- 
+2.51.0
+

diff --git a/0004-patch-Execute-subprocess-in-text-mode.patch b/0004-patch-Execute-subprocess-in-text-mode.patch
new file mode 100644
index 0000000..76696c0
--- /dev/null
+++ b/0004-patch-Execute-subprocess-in-text-mode.patch
@@ -0,0 +1,30 @@
+From f828c71a8aa080d8c95aea21396f5b799f610af4 Mon Sep 17 00:00:00 2001
+From: "FeRD (Frank Dana)" <ferdnyc@gmail.com>
+Date: Thu, 12 Jun 2025 05:49:15 -0400
+Subject: [PATCH 10/13] `patch`: Execute subprocess in text mode
+
+This prevents `fedpkg patch suffix` aborting with the error message
+"Could not execute patch: write() argument must be str, not bytes".
+
+Merges: https://pagure.io/rpkg/pull-request/744
+
+Signed-off-by: FeRD (Frank Dana) <ferdnyc@gmail.com>
+---
+ pyrpkg/__init__.py | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py
+index ad5ee31..a0fbb6d 100644
+--- a/pyrpkg/__init__.py
++++ b/pyrpkg/__init__.py
+@@ -2178,6 +2178,7 @@ class Commands(object):
+             self.log.debug('Running %s', ' '.join(cmd))
+             (output, errors) = subprocess.Popen(cmd, stdout=subprocess.PIPE,
+                                                 stderr=subprocess.PIPE,
++                                                universal_newlines=True,
+                                                 cwd=self.path).communicate()
+         except Exception as e:
+             raise rpkgError('Error running gendiff: %s' % e)
+-- 
+2.51.0
+

diff --git a/0005-type-fix-typo-in-requirements-README.patch b/0005-type-fix-typo-in-requirements-README.patch
new file mode 100644
index 0000000..a2bb057
--- /dev/null
+++ b/0005-type-fix-typo-in-requirements-README.patch
@@ -0,0 +1,24 @@
+From f487f5cd260ee4029c7545ffb7126997ded75600 Mon Sep 17 00:00:00 2001
+From: "Guillermo N." <gleiro@redhat.com>
+Date: Fri, 18 Jul 2025 20:47:37 +0200
+Subject: [PATCH 11/13] type: fix typo in requirements README.
+
+Signed-off-by: Guillermo N. <gleiro@redhat.com>
+---
+ requirements/README.rst | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/requirements/README.rst b/requirements/README.rst
+index 4e94bca..166c182 100644
+--- a/requirements/README.rst
++++ b/requirements/README.rst
+@@ -3,4 +3,5 @@ Requirements
+ 
+ * pypi.txt: contains Python packages that can be installed from PyPI via
+   ``pip``. Some of required packages are not available in PyPI as of writing
+-  this README file. They has to be installed from package manager too.
++  this README file. They have to be installed from package manager too.
++
+-- 
+2.51.0
+

diff --git a/0006-install-add-rpmbuild-arguments-with-and-without.patch b/0006-install-add-rpmbuild-arguments-with-and-without.patch
new file mode 100644
index 0000000..d236711
--- /dev/null
+++ b/0006-install-add-rpmbuild-arguments-with-and-without.patch
@@ -0,0 +1,132 @@
+From 04338101aa86d383e993358f349872fd0056168a Mon Sep 17 00:00:00 2001
+From: "Guillermo N." <gleiro@redhat.com>
+Date: Fri, 18 Jul 2025 20:55:19 +0200
+Subject: [PATCH 12/13] `install`: add rpmbuild arguments `--with` and
+ `--without`
+
+This commit introduces two new command-line flags for on-the-fly
+modification of `rpmbuild` arguments directly from the `install` subcommand:
+    - `--with <bcond>`: Appends a build condition (bcond) to `rpmbuild`
+      arguments.
+    - `--without <bcond>`: Removes or disables a build condition (bcond) from
+      `rpmbuild` arguments.
+
+These flags address the feature requested on `fedpkg` downstream repo.
+
+Resolves: https://pagure.io/fedpkg/issue/541
+
+Signed-off-by: Guillermo N. <gleiro@redhat.com>
+---
+ pyrpkg/__init__.py |  8 +++++++-
+ pyrpkg/cli.py      | 21 ++++++++++++++++++++-
+ tests/test_cli.py  |  2 ++
+ 3 files changed, 29 insertions(+), 2 deletions(-)
+
+diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py
+index a0fbb6d..41a84c2 100644
+--- a/pyrpkg/__init__.py
++++ b/pyrpkg/__init__.py
+@@ -2763,7 +2763,7 @@ class Commands(object):
+         self.kojisession.uploadWrapper(file, path, name=name, callback=callback)
+ 
+     def install(self, arch=None, short=False, builddir=None, nocheck=False,
+-                buildrootdir=None, define=None, extra_args=None):
++                buildrootdir=None, define=None, extra_args=None, installargs=None):
+         """Run ``rpmbuild -bi``
+ 
+         optionally for a specific arch, short-circuit it,
+@@ -2771,6 +2771,8 @@ class Commands(object):
+ 
+         Logs the output and returns nothing
+ 
++        :param list installargs: Modifiers for rpmbuild defaults (similar to
++    'extra_args' but derived from different command-line parsing).
+         :param str arch: specify a specific arch.
+         :param list define: specify a list of rpmbuild macros.
+         :param bool short: short-circuit it.
+@@ -2787,6 +2789,8 @@ class Commands(object):
+         # setup the rpm command
+         cmd = ['rpmbuild']
+         cmd.extend(self.rpmdefines)
++        if installargs:
++            cmd.extend(installargs)
+         if builddir:
+             # Tack on a new builddir to the end of the defines
+             cmd.extend(["--define", "_builddir %s" % os.path.abspath(builddir)])
+@@ -2905,6 +2909,8 @@ class Commands(object):
+         written into current working directory and in format
+         `.build-{version}-{release}.log`.
+ 
++        :param list localargs: Modifiers for rpmbuild defaults (similar to
++    'extra_args' but derived from different command-line parsing).
+         :param str arch: to optionally build for a specific arch.
+         :param list define: optional list of rpmbuild macros.
+         :param str hashtype: an alternative algorithm used for payload file
+diff --git a/pyrpkg/cli.py b/pyrpkg/cli.py
+index 8f5ae40..10c6fd4 100644
+--- a/pyrpkg/cli.py
++++ b/pyrpkg/cli.py
+@@ -1030,6 +1030,13 @@ class cliClient(object):
+             '--nocheck',
+             action='store_true',
+             help='nocheck install')
++        # Pass --with/without options to rpmbuild
++        install_parser.add_argument(
++            '--with', help='Enable configure option (bcond) for the build',
++            dest='bcond_with', action='append')
++        install_parser.add_argument(
++            '--without', help='Disable configure option (bcond) for the build',
++            dest='bcond_without', action='append')
+         install_parser.set_defaults(command=self.install, default=False)
+ 
+     def register_lint(self):
+@@ -2449,13 +2456,25 @@ class cliClient(object):
+ 
+     def install(self):
+         self.sources()
++
++        installargs = []
++
++        if self.args.bcond_with:
++            for arg in self.args.bcond_with:
++                installargs.extend(['--with', arg])
++
++        if self.args.bcond_without:
++            for arg in self.args.bcond_without:
++                installargs.extend(['--without', arg])
++
+         self.cmd.install(builddir=self.args.builddir,
+                          arch=self.args.arch,
+                          define=self.args.define,
+                          extra_args=self.extra_args,
+                          short=self.args.short_circuit,
+                          nocheck=self.args.nocheck,
+-                         buildrootdir=self.args.buildrootdir,)
++                         buildrootdir=self.args.buildrootdir,
++                         installargs=installargs)
+ 
+     def lint(self):
+         self.cmd.lint(self.args.info, self.args.rpmlintconf)
+diff --git a/tests/test_cli.py b/tests/test_cli.py
+index ae532b0..f734c43 100644
+--- a/tests/test_cli.py
++++ b/tests/test_cli.py
+@@ -865,6 +865,7 @@ class TestInstall(CliTestCase):
+         cli_cmd = [
+             'rpkg', '--path', self.cloned_repo_path, '--release', 'rhel-6',
+             '-q', 'install', '--nocheck', '--arch', 'i686',
++            '--with', 'a', '--without', 'b',
+             '--builddir', builddir, '--buildrootdir', buildrootdir
+         ]
+ 
+@@ -874,6 +875,7 @@ class TestInstall(CliTestCase):
+ 
+         spec = os.path.join(cli.cmd.path, cli.cmd.spec)
+         rpmbuild = ['rpmbuild'] + cli.cmd.rpmdefines + [
++            '--with', 'a', '--without', 'b',
+             '--define', '_builddir %s' % builddir, '--target', 'i686',
+             '--nocheck', '--quiet',
+             '--define', '_buildrootdir %s' % buildrootdir,
+-- 
+2.51.0
+

diff --git a/0007-srpm-man-page-generation-fixed.patch b/0007-srpm-man-page-generation-fixed.patch
new file mode 100644
index 0000000..d35197a
--- /dev/null
+++ b/0007-srpm-man-page-generation-fixed.patch
@@ -0,0 +1,37 @@
+From e8d209e9d66b13ad6eef5e84f7620781b0bbb6d8 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ond=C5=99ej=20Nosek?= <onosek@redhat.com>
+Date: Fri, 29 Aug 2025 01:07:49 +0200
+Subject: [PATCH 13/13] `srpm`: man page generation fixed
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Usage wasn't generated properly for this command. The usage was
+overridden with fixed text instead of automatic generation.
+
+Relates: #751
+
+Signed-off-by: Ondřej Nosek <onosek@redhat.com>
+---
+ pyrpkg/cli.py | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/pyrpkg/cli.py b/pyrpkg/cli.py
+index 10c6fd4..9fbb166 100644
+--- a/pyrpkg/cli.py
++++ b/pyrpkg/cli.py
+@@ -1548,9 +1548,10 @@ class cliClient(object):
+         srpm_parser = self.subparsers.add_parser(
+             'srpm', help='Create a source rpm',
+             parents=[self.rpm_parser_common],
+-            usage='Create a source rpm',
+             formatter_class=argparse.RawDescriptionHelpFormatter,
+             description=textwrap.dedent("""
++                Create a source rpm
++
+                 This command wraps "rpmbuild -bs", roughly equivalent to:
+ 
+                   rpmbuild -bs mypackage.spec \\
+-- 
+2.51.0
+

diff --git a/rpkg.spec b/rpkg.spec
index 44d19cc..70e68de 100644
--- a/rpkg.spec
+++ b/rpkg.spec
@@ -1,6 +1,6 @@
 Name:           rpkg
 Version:        1.68
-Release:        5%{?dist}
+Release:        6%{?dist}
 
 Summary:        Python library for interacting with rpm+git
 # Automatically converted from old format: GPLv2+ and LGPLv2 - review is highly recommended.
@@ -25,10 +25,12 @@ Source0:        https://pagure.io/releases/rpkg/%{name}-%{version}.tar.gz
 
 # No support for setup.py since Python 3.12 (RHEL 10)
 # hatchling is supported in >Python 3.6 releases (RHEL 8)
-%if 0%{?rhel} >= 9 || 0%{?fedora} >= 41
-%global with_hatchling 1
-%else
+%if 0%{?rhel} && 0%{?rhel} <= 8
 %global with_hatchling 0
+%{echo:--> with_hatchling unset, 0%{?rhel} %{?fedora}}
+%else
+%global with_hatchling 1
+%{echo:--> with_hatchling set, 0%{?rhel} %{?fedora}}
 %endif
 
 
@@ -46,7 +48,12 @@ Patch0:         remove-koji-and-rpm-py-installer-from-requires.patch
 %if 0%{?with_python2}
 Patch1:         0001-Remove-Environment-Markers-syntax.patch
 %endif
-
+Patch2:         0002-pre-push-check-bogus-error-file-wasn-t-listed.patch
+Patch3:         0003-Fix-mockbuild-srpm-mock-specfile_path.patch
+Patch4:         0004-patch-Execute-subprocess-in-text-mode.patch
+Patch5:         0005-type-fix-typo-in-requirements-README.patch
+Patch6:         0006-install-add-rpmbuild-arguments-with-and-without.patch
+Patch7:         0007-srpm-man-page-generation-fixed.patch
 
 %description
 Python library for interacting with rpm+git
@@ -277,6 +284,14 @@ example_cli_dir=$RPM_BUILD_ROOT%{_datadir}/%{name}/examples/cli
 
 
 %changelog
+* Tue Sep 02 2025 Ondřej Nosek <onosek@redhat.com> - 1.68-6
+- Patch: `pre-push-check`: bogus error - file wasn't listed
+- Patch: Fix mockbuild --srpm-mock specfile_path
+- Patch: `patch`: Execute subprocess in text mode
+- Patch: type: fix typo in requirements README.
+- Patch: `install`: add rpmbuild arguments `--with` and `--without`
+- Patch: `srpm`: man page generation fixed
+
 * Fri Aug 15 2025 Python Maint <python-maint@redhat.com> - 1.68-5
 - Rebuilt for Python 3.14.0rc2 bytecode
 

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [rpms/rpkg] 1.70-1: A few patches:
@ 2026-08-10 21:44 
  0 siblings, 0 replies; 6+ messages in thread
From:  @ 2026-08-10 21:44 UTC (permalink / raw)
  To: git-commits

            A new commit has been pushed.

            Repo   : rpms/rpkg
            Branch : 1.70-1
            Commit : 30368f20cf85f80c2396e9ff0ec3b11837a67558
            Author : Ondřej Nosek <onosek@redhat.com>
            Date   : 2024-12-10T02:24:17+00:00
            Stats  : +199/-1 in 4 file(s)
            URL    : https://src.fedoraproject.org/rpms/rpkg/c/30368f20cf85f80c2396e9ff0ec3b11837a67558?branch=1.70-1

            Log:
            A few patches:

- Patch: `chain-build`: correct the info message
- Patch: Fix regular expression for parsing Source lines
- Patch: Add draft builds support

Signed-off-by: Ondřej Nosek <onosek@redhat.com>

---
diff --git a/0006-Add-draft-builds-support.patch b/0006-Add-draft-builds-support.patch
new file mode 100644
index 0000000..9eb57fb
--- /dev/null
+++ b/0006-Add-draft-builds-support.patch
@@ -0,0 +1,98 @@
+From 53a12c6fea813598851af65390695a69c8f29b76 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ond=C5=99ej=20Nosek?= <onosek@redhat.com>
+Date: Wed, 9 Oct 2024 03:24:51 +0200
+Subject: [PATCH 1/3] Add draft builds support
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Generally, it means adding `--draft` argument to the koji build
+command.
+
+JIRA: RHELCMP-14108
+
+Signed-off-by: Ondřej Nosek <onosek@redhat.com>
+---
+ pyrpkg/__init__.py |  6 +++++-
+ pyrpkg/cli.py      | 11 +++++++++--
+ 2 files changed, 14 insertions(+), 3 deletions(-)
+
+diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py
+index 573fc36..c3e1722 100644
+--- a/pyrpkg/__init__.py
++++ b/pyrpkg/__init__.py
+@@ -2456,7 +2456,7 @@ class Commands(object):
+ 
+     def build(self, skip_tag=False, scratch=False, background=False,
+               url=None, chain=None, arches=None, sets=False, nvr_check=True,
+-              fail_fast=False, custom_user_metadata=None):
++              fail_fast=False, custom_user_metadata=None, draft=False):
+         """Initiate a build in build system
+ 
+         :param bool skip_tag: Skip the tag action after the build.
+@@ -2473,6 +2473,7 @@ class Commands(object):
+             will cause the entire build to fail if any subtask/architecture
+             build fails.
+         :param str custom_user_metadata: JSON string of custom metadata
++        :param bool draft: Perform a draft build. Default is False.
+         :return: task ID returned from Koji API ``build`` and ``chainBuild``.
+         :rtype: int
+         """
+@@ -2524,6 +2525,9 @@ class Commands(object):
+         if scratch:
+             opts['scratch'] = True
+             cmd.append('--scratch')
++        if draft:
++            opts['draft'] = True
++            cmd.append('--draft')
+         if background:
+             cmd.append('--background')
+             priority = 5  # magic koji number :/
+diff --git a/pyrpkg/cli.py b/pyrpkg/cli.py
+index 97c2904..bf2cfa1 100644
+--- a/pyrpkg/cli.py
++++ b/pyrpkg/cli.py
+@@ -548,9 +548,13 @@ class cliClient(object):
+         build_parser.add_argument(
+             '--skip-tag', action='store_true', default=False,
+             help='Do not attempt to tag package')
+-        build_parser.add_argument(
++        build_type_group = build_parser.add_mutually_exclusive_group()
++        build_type_group.add_argument(
+             '--scratch', action='store_true', default=False,
+             help='Perform a scratch build')
++        build_type_group.add_argument(
++            '--draft', action='store_true', default=False,
++            help='Perform a draft build')
+         build_parser.add_argument(
+             '--srpm', nargs='?', const='CONSTRUCT',
+             help='Build from an srpm. If no srpm is provided with this option'
+@@ -2125,7 +2129,8 @@ class cliClient(object):
+             sets=sets,
+             nvr_check=nvr_check,
+             fail_fast=self.args.fail_fast,
+-            custom_user_metadata=custom_user_metadata)
++            custom_user_metadata=custom_user_metadata,
++            draft=self.args.draft)
+ 
+     def chainbuild(self):
+         """Implement chain-build command"""
+@@ -2176,6 +2181,7 @@ class cliClient(object):
+         self.args.chain = urls
+         self.args.skip_tag = False
+         self.args.scratch = False
++        self.args.draft = False
+         return self.build(sets)
+ 
+     def clean(self):
+@@ -2936,6 +2942,7 @@ class cliClient(object):
+         # A scratch build is just a build with --scratch
+         self.args.scratch = True
+         self.args.skip_tag = False
++        self.args.draft = False
+         return self.build()
+ 
+     def sources(self):
+-- 
+2.47.1
+

diff --git a/0007-Fix-regular-expression-for-parsing-Source-lines.patch b/0007-Fix-regular-expression-for-parsing-Source-lines.patch
new file mode 100644
index 0000000..d6301c8
--- /dev/null
+++ b/0007-Fix-regular-expression-for-parsing-Source-lines.patch
@@ -0,0 +1,54 @@
+From 2a9507f1882bc6dbcf49f9dd39cbff451d41f1c9 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ond=C5=99ej=20Nosek?= <onosek@redhat.com>
+Date: Mon, 14 Oct 2024 01:39:42 +0200
+Subject: [PATCH 2/3] Fix regular expression for parsing Source lines
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+When pushing changes to the dist-git repo, the `pre-push-check`
+didn't identify hidden files (.file) among 'SourceX|PatchX'
+definitions. The regular expression was taken from another part
+of the code and improved.
+
+Fixes: #721
+JIRA: RHELCMP-13881
+
+Signed-off-by: Ondřej Nosek <onosek@redhat.com>
+---
+ pyrpkg/__init__.py | 5 +++--
+ pyrpkg/spec.py     | 2 +-
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py
+index c3e1722..fd953b3 100644
+--- a/pyrpkg/__init__.py
++++ b/pyrpkg/__init__.py
+@@ -4575,8 +4575,9 @@ class Commands(object):
+         source_files = []
+         # extract source files from the spectool's output
+         for line in stdout.split('\n'):
+-            file_location = re.sub(r'(?:Source|Patch)\d+\s*:\s*(\w+)', r'\1', line, re.IGNORECASE)
+-            if file_location:
++            match = SpecFile.sourcefile_expression.match(line)
++            if match:
++                file_location = match.group('val')
+                 # find out the format of the source file path. From URL use just the file name.
+                 # We want to keep hierarchy of the files if possible
+                 res = urllib.parse.urlparse(file_location)
+diff --git a/pyrpkg/spec.py b/pyrpkg/spec.py
+index 5400de3..28e3a27 100644
+--- a/pyrpkg/spec.py
++++ b/pyrpkg/spec.py
+@@ -15,7 +15,7 @@ from pyrpkg.errors import rpkgError
+ class SpecFile(object):
+     """Simple specfile parser that finds source file names"""
+     sourcefile_expression = re.compile(
+-        r'^((source[0-9]*|patch[0-9]*)\s*:\s*(?P<val>.*))\s*$',
++        r'^(?:Source|Patch)\d*\s*:\s*(?P<val>[^\s]+)\s*$',
+         re.IGNORECASE)
+ 
+     def __init__(self, spec, rpmdefines):
+-- 
+2.47.1
+

diff --git a/0008-chain-build-correct-the-info-message.patch b/0008-chain-build-correct-the-info-message.patch
new file mode 100644
index 0000000..89119a7
--- /dev/null
+++ b/0008-chain-build-correct-the-info-message.patch
@@ -0,0 +1,38 @@
+From f3cbcdd3b08311755940cb23dae131bbed901f9c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ond=C5=99ej=20Nosek?= <onosek@redhat.com>
+Date: Wed, 16 Oct 2024 02:57:52 +0200
+Subject: [PATCH 3/3] `chain-build`: correct the info message
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The info message was missing the whole 'chain' which says what
+components will be built. Originally, it didn't contain the last
+group of components. It was confusing for users.
+
+Fixes: https://pagure.io/fedpkg/issue/567
+JIRA: RHELCMP-14076
+
+Signed-off-by: Ondřej Nosek <onosek@redhat.com>
+---
+ pyrpkg/__init__.py | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py
+index fd953b3..dfccad3 100644
+--- a/pyrpkg/__init__.py
++++ b/pyrpkg/__init__.py
+@@ -2596,8 +2596,8 @@ class Commands(object):
+             cmd.extend(' : '.join(
+                 [' '.join(build_sets) for build_sets in chain]
+             ).split())
+-            self.log.info('Chain building %s + %s for %s',
+-                          build_reference, chain[:-1], self.target)
++            self.log.info('Chain building %s, chain consists of %s, for %s',
++                          build_reference, chain, self.target)
+             self.log.debug(
+                 'Building chain %s for %s with options %s and a priority '
+                 'of %s', chain, self.target, opts, priority)
+-- 
+2.47.1
+

diff --git a/rpkg.spec b/rpkg.spec
index c956f52..f15df43 100644
--- a/rpkg.spec
+++ b/rpkg.spec
@@ -1,6 +1,6 @@
 Name:           rpkg
 Version:        1.67
-Release:        4%{?dist}
+Release:        5%{?dist}
 
 Summary:        Python library for interacting with rpm+git
 # Automatically converted from old format: GPLv2+ and LGPLv2 - review is highly recommended.
@@ -47,6 +47,9 @@ Patch3:         0003-Remove-Environment-Markers-syntax.patch
 %endif
 Patch4:         0004-Fix-package-in-Pypi.patch
 Patch5:         0005-Fixing-encoding-of-the-url-when-checking-lookaside.patch
+Patch6:         0006-Add-draft-builds-support.patch
+Patch7:         0007-Fix-regular-expression-for-parsing-Source-lines.patch
+Patch8:         0008-chain-build-correct-the-info-message.patch
 
 
 %description
@@ -278,6 +281,11 @@ example_cli_dir=$RPM_BUILD_ROOT%{_datadir}/%{name}/examples/cli
 
 
 %changelog
+* Tue Dec 10 2024 Ondřej Nosek <onosek@redhat.com> - 1.67-5
+- Patch: `chain-build`: correct the info message
+- Patch: Fix regular expression for parsing Source lines
+- Patch: Add draft builds support
+
 * Mon Sep 16 2024 Ondřej Nosek <onosek@redhat.com> - 1.67-4
 - Patch: Fixing encoding of the url when checking lookaside
 - Patch: Fix package in Pypi

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [rpms/rpkg] 1.70-1: A few patches:
@ 2026-08-10 21:44 
  0 siblings, 0 replies; 6+ messages in thread
From:  @ 2026-08-10 21:44 UTC (permalink / raw)
  To: git-commits

            A new commit has been pushed.

            Repo   : rpms/rpkg
            Branch : 1.70-1
            Commit : 4d309050b8a601efc3b290e6f29d3af78daa7228
            Author : Ondřej Nosek <onosek@redhat.com>
            Date   : 2024-09-17T23:47:31+00:00
            Stats  : +153/-6 in 3 file(s)
            URL    : https://src.fedoraproject.org/rpms/rpkg/c/4d309050b8a601efc3b290e6f29d3af78daa7228?branch=1.70-1

            Log:
            A few patches:

- Patch: Fixing encoding of the url when checking lookaside
- Patch: Fix package in Pypi

Signed-off-by: Ondřej Nosek <onosek@redhat.com>

---
diff --git a/0004-Fix-package-in-Pypi.patch b/0004-Fix-package-in-Pypi.patch
new file mode 100644
index 0000000..e82222f
--- /dev/null
+++ b/0004-Fix-package-in-Pypi.patch
@@ -0,0 +1,48 @@
+From 69a62d90ccab505bdd95b9817415b93582541d6c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ond=C5=99ej=20Nosek?= <onosek@redhat.com>
+Date: Mon, 8 Jul 2024 02:29:04 +0200
+Subject: [PATCH 1/2] Fix package in Pypi
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The pyrpkg module couldn't be imported.
+Flake8 doesn't need installation of all dependencies - quicker.
+
+Signed-off-by: Ondřej Nosek <onosek@redhat.com>
+---
+ pyproject.toml | 4 ++--
+ tox.ini        | 2 ++
+ 2 files changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/pyproject.toml b/pyproject.toml
+index 9d41225..dc4a285 100644
+--- a/pyproject.toml
++++ b/pyproject.toml
+@@ -83,5 +83,5 @@ include = [
+ 
+ [tool.hatch.build.targets.wheel]
+ packages = [
+-    "dist/rpkg",
++    "pyrpkg",
+ ]
+diff --git a/tox.ini b/tox.ini
+index 3357e2d..2638246 100644
+--- a/tox.ini
++++ b/tox.ini
+@@ -34,10 +34,12 @@ sitepackages=true
+ sitepackages=true
+ 
+ [testenv:flake8]
++skip_install = True
+ deps = flake8
+ commands = python -m flake8 pyrpkg/ tests/
+ 
+ [testenv:flake8python2]
++skip_install = True
+ deps = flake8
+ commands = python -m flake8 pyrpkg/ tests/
+ 
+-- 
+2.46.0
+

diff --git a/0005-Fixing-encoding-of-the-url-when-checking-lookaside.patch b/0005-Fixing-encoding-of-the-url-when-checking-lookaside.patch
new file mode 100644
index 0000000..0801d00
--- /dev/null
+++ b/0005-Fixing-encoding-of-the-url-when-checking-lookaside.patch
@@ -0,0 +1,72 @@
+From 4a1ed7633aad84c8e3bd9e856b5d8d95136a739d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ond=C5=99ej=20Nosek?= <onosek@redhat.com>
+Date: Thu, 12 Sep 2024 00:28:04 +0200
+Subject: [PATCH 2/2] Fixing encoding of the url when checking lookaside
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+In RHEL-7 (Python 2.7) encoding of the url was unicode. Curl's
+method 'setopt' expects utf-8.
+
+JIRA: RHELCMP-13939
+
+Signed-off-by: Ondřej Nosek <onosek@redhat.com>
+---
+ pyrpkg/lookaside.py     |  4 +++-
+ tests/test_lookaside.py | 10 ++++++++--
+ 2 files changed, 11 insertions(+), 3 deletions(-)
+
+diff --git a/pyrpkg/lookaside.py b/pyrpkg/lookaside.py
+index 72109bf..5929fc9 100644
+--- a/pyrpkg/lookaside.py
++++ b/pyrpkg/lookaside.py
+@@ -167,7 +167,7 @@ class CGILookasideCache(object):
+         self.log.info("Downloading %s from %s", filename, self.download_url)
+         urled_file = urllib.parse.quote(filename)
+         url = self.get_download_url(name, urled_file, hash, hashtype, **kwargs)
+-        if isinstance(url, six.text_type):
++        if six.PY2 and isinstance(url, six.text_type):
+             url = url.encode('utf-8')
+         self.log.debug("Full url: %s", url)
+ 
+@@ -215,6 +215,8 @@ class CGILookasideCache(object):
+ 
+         urled_file = urllib.parse.quote(filename)
+         url = self.get_download_url(name, urled_file, hash, hashtype or self.hashtype)
++        if six.PY2 and isinstance(url, six.text_type):
++            url = url.encode('utf-8')
+ 
+         c = pycurl.Curl()
+         c.setopt(pycurl.URL, url)
+diff --git a/tests/test_lookaside.py b/tests/test_lookaside.py
+index 12da113..6bace2e 100644
+--- a/tests/test_lookaside.py
++++ b/tests/test_lookaside.py
+@@ -112,7 +112,10 @@ class CGILookasideCacheTestCase(unittest.TestCase):
+         lc = CGILookasideCache('sha512', 'http://example.com', '_')
+         lc.download(name, filename, hash, outfile, hashtype='sha512')
+         self.assertEqual(curl.perform.call_count, 1)
+-        self.assertEqual(curlopts[pycurl.URL].decode('utf-8'), full_url)
++        if six.PY2:
++            self.assertEqual(curlopts[pycurl.URL].decode('utf-8'), full_url)
++        else:
++            self.assertEqual(curlopts[pycurl.URL], full_url)
+         self.assertEqual(os.path.getmtime(outfile), 0)
+ 
+         with open(outfile) as f:
+@@ -167,7 +170,10 @@ class CGILookasideCacheTestCase(unittest.TestCase):
+         lc.download(name, filename, hash, outfile, hashtype='sha512',
+                     branch=branch)
+         self.assertEqual(curl.perform.call_count, 1)
+-        self.assertEqual(curlopts[pycurl.URL].decode('utf-8'), full_url)
++        if six.PY2:
++            self.assertEqual(curlopts[pycurl.URL].decode('utf-8'), full_url)
++        else:
++            self.assertEqual(curlopts[pycurl.URL], full_url)
+ 
+     @mock.patch('pyrpkg.lookaside.pycurl.Curl')
+     def test_download_corrupted(self, mock_curl):
+-- 
+2.46.0
+

diff --git a/rpkg.spec b/rpkg.spec
index df1f182..c956f52 100644
--- a/rpkg.spec
+++ b/rpkg.spec
@@ -1,6 +1,6 @@
 Name:           rpkg
 Version:        1.67
-Release:        3%{?dist}
+Release:        4%{?dist}
 
 Summary:        Python library for interacting with rpm+git
 # Automatically converted from old format: GPLv2+ and LGPLv2 - review is highly recommended.
@@ -23,6 +23,13 @@ Source0:        https://pagure.io/releases/rpkg/%{name}-%{version}.tar.gz
 %global with_python3 1
 %endif
 
+# No support for setup.py since Python 3.12 (RHEL 10)
+%if 0%{?rhel} >= 10
+%global with_hatchling 1
+%else
+%global with_hatchling 0
+%endif
+
 
 # Fix for bug 1579367
 # Due to https://pagure.io/koji/issue/912, python[23]-koji package does not
@@ -38,6 +45,8 @@ Patch2:         0002-Remove-pytest-coverage-execution.patch
 %if 0%{?with_python2}
 Patch3:         0003-Remove-Environment-Markers-syntax.patch
 %endif
+Patch4:         0004-Fix-package-in-Pypi.patch
+Patch5:         0005-Fixing-encoding-of-the-url-when-checking-lookaside.patch
 
 
 %description
@@ -124,11 +133,17 @@ BuildRequires:  python3-openidc-client
 BuildRequires:  python3-pycurl
 BuildRequires:  python3-six >= 1.9.0
 BuildRequires:  python3-requests
-BuildRequires:  python3-setuptools
 BuildRequires:  python3-pytest
 BuildRequires:  python3-PyYAML
 BuildRequires:  rpmlint
 BuildRequires:  rpmdevtools
+%if 0%{?with_hatchling}
+BuildRequires:  pyproject-rpm-macros
+BuildRequires:  python3-hatchling
+BuildRequires:  python3-pip
+%else
+BuildRequires:  python3-setuptools
+%endif
 
 Requires:       mock
 Requires:       redhat-rpm-config
@@ -177,18 +192,18 @@ Common files for python2-%{name} and python3-%{name}.
 %prep
 %autosetup -p1
 
-# Removes section from setup.py that is relevant only for pip and
-# is not compatible with in RHEL-6 tools
-sed -i -n '/extras_require/,/}/!p' setup.py
-
 %build
 %if 0%{?with_python2}
 %{__python2} setup.py build
 %endif
 
 %if 0%{?with_python3}
+%if 0%{?with_hatchling}
+%pyproject_wheel
+%else
 %py3_build
 %endif
+%endif
 
 
 %install
@@ -197,8 +212,12 @@ sed -i -n '/extras_require/,/}/!p' setup.py
 %endif
 
 %if 0%{?with_python3}
+%if 0%{?with_hatchling}
+%pyproject_install
+%else
 %py3_install
 %endif
+%endif
 
 
 # Create configuration directory to holding downstream clients config files
@@ -246,8 +265,12 @@ example_cli_dir=$RPM_BUILD_ROOT%{_datadir}/%{name}/examples/cli
 %doc README.rst CHANGELOG.rst
 %license COPYING COPYING-koji LGPL
 %{python3_sitelib}/pyrpkg
+%if 0%{?with_hatchling}
+%{python3_sitelib}/%{name}-%{version}.dist-info
+%else
 %{python3_sitelib}/%{name}-%{version}-py*.egg-info
 %endif
+%endif
 
 %files common
 %{_datadir}/%{name}
@@ -255,6 +278,10 @@ example_cli_dir=$RPM_BUILD_ROOT%{_datadir}/%{name}/examples/cli
 
 
 %changelog
+* Mon Sep 16 2024 Ondřej Nosek <onosek@redhat.com> - 1.67-4
+- Patch: Fixing encoding of the url when checking lookaside
+- Patch: Fix package in Pypi
+
 * Fri Jul 19 2024 Fedora Release Engineering <releng@fedoraproject.org> - 1.67-2
 - Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild
 

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [rpms/rpkg] 1.70-1: A few patches:
@ 2026-08-10 21:44 
  0 siblings, 0 replies; 6+ messages in thread
From:  @ 2026-08-10 21:44 UTC (permalink / raw)
  To: git-commits

            A new commit has been pushed.

            Repo   : rpms/rpkg
            Branch : 1.70-1
            Commit : d35e81155f584afe442b3bed369915257a4f485b
            Author : Ondřej Nosek <onosek@redhat.com>
            Date   : 2023-08-20T20:58:32+00:00
            Stats  : +111/-1 in 3 file(s)
            URL    : https://src.fedoraproject.org/rpms/rpkg/c/d35e81155f584afe442b3bed369915257a4f485b?branch=1.70-1

            Log:
            A few patches:

- Patch: Support for checking exploded sources before push
- Patch: Split git credential data on first = only

Signed-off-by: Ondřej Nosek <onosek@redhat.com>

---
diff --git a/0023-Split-git-credential-data-on-first-only.patch b/0023-Split-git-credential-data-on-first-only.patch
new file mode 100644
index 0000000..43416b7
--- /dev/null
+++ b/0023-Split-git-credential-data-on-first-only.patch
@@ -0,0 +1,33 @@
+From 75d42bad79b54654fca9770a2857e79e82d83c3e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Lubom=C3=ADr=20Sedl=C3=A1=C5=99?= <lsedlar@redhat.com>
+Date: Wed, 21 Jun 2023 10:42:45 +0200
+Subject: [PATCH 1/3] Split git credential data on first = only
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The value itself can contain a = character, but we don't really care
+about that. We can treat the value of the key as opaque.
+
+Fixes: https://pagure.io/rpkg/issue/694
+Signed-off-by: Lubomír Sedlář <lsedlar@redhat.com>
+---
+ pyrpkg/cli.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/pyrpkg/cli.py b/pyrpkg/cli.py
+index 020a247..1bd7979 100644
+--- a/pyrpkg/cli.py
++++ b/pyrpkg/cli.py
+@@ -824,7 +824,7 @@ class cliClient(object):
+         """Parses the git-credential-helper IO format input."""
+         inp = {}
+         for line in sys.stdin:
+-            vals = line.split('=', 2)
++            vals = line.split('=', 1)
+             if len(vals) != 2:
+                 print('Invalid input: %s' % line, file=sys.stderr)
+                 return False
+-- 
+2.41.0
+

diff --git a/0024-Support-for-checking-exploded-sources-before-push.patch b/0024-Support-for-checking-exploded-sources-before-push.patch
new file mode 100644
index 0000000..e8f14de
--- /dev/null
+++ b/0024-Support-for-checking-exploded-sources-before-push.patch
@@ -0,0 +1,71 @@
+From 87d4995b40fbcddac88fb21191eb2d5d1f248550 Mon Sep 17 00:00:00 2001
+From: Ondrej Nosek <onosek@redhat.com>
+Date: Tue, 11 Jul 2023 17:00:48 +0200
+Subject: [PATCH 2/3] Support for checking exploded sources before push
+
+pre-push-check now includes test whether source files listed
+in a specfile come from additional sources.
+This functionality is relevant only for some x-pkg tools, others
+should not be affected.
+
+JIRA: RHELCMP-11777
+
+Signed-off-by: Ondrej Nosek <onosek@redhat.com>
+---
+ pyrpkg/__init__.py                    | 12 ++++++++++--
+ tests/commands/test_pre_push_check.py |  4 ++--
+ 2 files changed, 12 insertions(+), 4 deletions(-)
+
+diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py
+index b45ad8f..bc669b9 100644
+--- a/pyrpkg/__init__.py
++++ b/pyrpkg/__init__.py
+@@ -4468,6 +4468,10 @@ class Commands(object):
+ 
+         return self._repo_name, version, release
+ 
++    # Works as virtual method. Other x-pkg tools can add their specific sources
++    def additional_source_entries(self):
++        return {}
++
+     def pre_push_check(self, ref):
+         show_hint = ('Hint: this check (.git/hooks/pre-push script) can be bypassed by adding '
+                      'the argument \'--no-verify\' argument to the push command.')
+@@ -4561,13 +4565,17 @@ class Commands(object):
+         # list of all files (their relative paths) in the commit
+         repo_entries = set(item.path for item in commit.tree.traverse() if item.type != "tree")
+ 
++        # other x-pkg tools can add their specific sources
++        additional_entries = set(self.additional_source_entries())
++
+         # check whether every source file is either listed in the 'sources' file or tracked in git
+         for source_file in source_files:
+             listed = source_file in sourcesf_entries
+             tracked = source_file in repo_entries
+-            if not (listed or tracked):
++            listed_additional = source_file in additional_entries
++            if not (listed or tracked or listed_additional):
+                 self.log.error('Source file \'{0}\' was neither listed in the \'sources\' file '
+-                               'nor tracked in git. '
++                               'nor tracked in git nor listed in additional sources. '
+                                'Push operation was cancelled'.format(source_file))
+                 self.log.warning(show_hint)
+                 sys.exit(4)
+diff --git a/tests/commands/test_pre_push_check.py b/tests/commands/test_pre_push_check.py
+index ee151c1..79165ec 100644
+--- a/tests/commands/test_pre_push_check.py
++++ b/tests/commands/test_pre_push_check.py
+@@ -90,8 +90,8 @@ Patch3: d.patch
+ 
+         self.assertEqual(exc.exception.code, 4)
+         log_error.assert_called_once_with("Source file 'b.patch' was neither listed in the "
+-                                          "'sources' file nor tracked in git. Push operation "
+-                                          "was cancelled")
++                                          "'sources' file nor tracked in git nor listed "
++                                          "in additional sources. Push operation was cancelled")
+ 
+         # Verify added files are committed but not pushed to origin
+         local_repo = git.Repo(self.cloned_dir)
+-- 
+2.41.0
+

diff --git a/rpkg.spec b/rpkg.spec
index 8d1cb8f..346816d 100644
--- a/rpkg.spec
+++ b/rpkg.spec
@@ -1,6 +1,6 @@
 Name:           rpkg
 Version:        1.66
-Release:        10%{?dist}
+Release:        11%{?dist}
 
 Summary:        Python library for interacting with rpm+git
 License:        GPLv2+ and LGPLv2
@@ -56,6 +56,8 @@ Patch19:        0019-Pre-push-hook-won-t-check-private-branches.patch
 Patch20:        0020-Use-release-s-rpmdefines-in-unused-sources-check.patch
 Patch21:        0021-Do-not-require-sources-file-for-all-namespaces.patch
 Patch22:        0022-commit-command-fails-on-containers-namespace.patch
+Patch23:        0023-Split-git-credential-data-on-first-only.patch
+Patch24:        0024-Support-for-checking-exploded-sources-before-push.patch
 
 %description
 Python library for interacting with rpm+git
@@ -272,6 +274,10 @@ example_cli_dir=$RPM_BUILD_ROOT%{_datadir}/%{name}/examples/cli
 
 
 %changelog
+* Sun Aug 20 2023 Ondřej Nosek <onosek@redhat.com> - 1.66-11
+- Patch: Support for checking exploded sources before push
+- Patch: Split git credential data on first = only
+
 * Fri Jul 21 2023 Fedora Release Engineering <releng@fedoraproject.org> - 1.66-10
 - Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild
 

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [rpms/rpkg] 1.70-1: A few patches:
@ 2026-08-10 21:44 
  0 siblings, 0 replies; 6+ messages in thread
From:  @ 2026-08-10 21:44 UTC (permalink / raw)
  To: git-commits

            A new commit has been pushed.

            Repo   : rpms/rpkg
            Branch : 1.70-1
            Commit : e78ad805c297ae46eb38e788dba0c62509ac5ba8
            Author : Ondřej Nosek <onosek@redhat.com>
            Date   : 2023-04-28T10:42:36+00:00
            Stats  : +237/-1 in 3 file(s)
            URL    : https://src.fedoraproject.org/rpms/rpkg/c/e78ad805c297ae46eb38e788dba0c62509ac5ba8?branch=1.70-1

            Log:
            A few patches:

- Patch: Do not require 'sources' file for all namespaces
- Use release's rpmdefines in unused sources check

Signed-off-by: Ondřej Nosek <onosek@redhat.com>

---
diff --git a/0020-Use-release-s-rpmdefines-in-unused-sources-check.patch b/0020-Use-release-s-rpmdefines-in-unused-sources-check.patch
new file mode 100644
index 0000000..6be7cee
--- /dev/null
+++ b/0020-Use-release-s-rpmdefines-in-unused-sources-check.patch
@@ -0,0 +1,170 @@
+From 8667d5379161183b306bdd4a6733c666cd2ef310 Mon Sep 17 00:00:00 2001
+From: Otto Liljalaakso <otto.liljalaakso@iki.fi>
+Date: Sun, 2 Apr 2023 17:21:00 +0300
+Subject: [PATCH 1/2] Use release's rpmdefines in unused sources check
+
+Conditional Source: tags are problematic and, in fact, forbidden in at
+least Fedora. However, there are packages that conditionalize packages
+based on macros such as %{rhel} or %{fedora}. 'x-pkg sources' did not
+handle such packages correctly, because when the specfile was parsed
+to check for unused sources, values for those macros were not set. This
+was different from other commands which set such macros based on the
+value of --release parameter or Git branch name.
+
+Improve support for conditional Source: tags by using the standard set
+of rpmdefines when the specfile is parsed in 'fedpkg sources'.
+
+Fixes: #671
+JIRA: RHELCMP-11465
+Merges: https://pagure.io/rpkg/pull-request/678
+
+Signed-off-by: Otto Liljalaakso <otto.liljalaakso@iki.fi>
+---
+ pyrpkg/__init__.py | 21 +++++++++++++++------
+ pyrpkg/spec.py     | 12 +++++++-----
+ tests/test_cli.py  | 21 ++++++++++++++++++++-
+ tests/test_spec.py |  8 ++++++--
+ 4 files changed, 48 insertions(+), 14 deletions(-)
+
+diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py
+index 3f934d3..817ef33 100644
+--- a/pyrpkg/__init__.py
++++ b/pyrpkg/__init__.py
+@@ -2261,13 +2261,22 @@ class Commands(object):
+         sourcesf = SourcesFile(self.sources_filename, self.source_entry_type)
+ 
+         try:
+-            specf = SpecFile(os.path.join(self.layout.specdir, self.spec),
+-                             self.layout.sourcedir)
+-            spec_parsed = True
+-        except Exception:
+-            self.log.warning("Parsing specfile for used sources failed. "
+-                             "Falling back to downloading all sources.")
++            # Try resolving rpmdefines separately. This produces a clear error
++            # message in the common failure case of custom branch name.
++            self.rpmdefines
++        except Exception as err:
++            self.log.warning("Parsing specfile for used sources failed: %s" % err)
++            self.log.warning("Falling back to downloading all sources.")
+             spec_parsed = False
++        else:
++            try:
++                specf = SpecFile(os.path.join(self.layout.specdir, self.spec),
++                                 self.rpmdefines)
++                spec_parsed = True
++            except Exception:
++                self.log.warning("Parsing specfile for used sources failed. "
++                                 "Falling back to downloading all sources.")
++                spec_parsed = False
+ 
+         args = dict()
+         if self.lookaside_request_params:
+diff --git a/pyrpkg/spec.py b/pyrpkg/spec.py
+index d72f1fb..5400de3 100644
+--- a/pyrpkg/spec.py
++++ b/pyrpkg/spec.py
+@@ -18,16 +18,16 @@ class SpecFile(object):
+         r'^((source[0-9]*|patch[0-9]*)\s*:\s*(?P<val>.*))\s*$',
+         re.IGNORECASE)
+ 
+-    def __init__(self, spec, sourcedir):
++    def __init__(self, spec, rpmdefines):
+         self.spec = spec
+-        self.sourcedir = sourcedir
++        self.rpmdefines = rpmdefines
+         self.sources = []
+ 
+         self.parse()
+ 
+     def parse(self):
+         """Call rpmspec and find source tags from the result."""
+-        stdout = run(self.spec, self.sourcedir)
++        stdout = run(self.spec, self.rpmdefines)
+         for line in stdout.splitlines():
+             m = self.sourcefile_expression.match(line)
+             if not m:
+@@ -38,8 +38,10 @@ class SpecFile(object):
+             self.sources.append(val)
+ 
+ 
+-def run(spec, sourcedir):
+-    cmdline = ['rpmspec', '--define', "_sourcedir %s" % sourcedir, '-P', spec]
++def run(spec, rpmdefines):
++    cmdline = ['rpmspec']
++    cmdline.extend(rpmdefines)
++    cmdline.extend(['-P', spec])
+     try:
+         process = subprocess.Popen(cmdline,
+                                    stdout=subprocess.PIPE,
+diff --git a/tests/test_cli.py b/tests/test_cli.py
+index 02620ef..58df047 100644
+--- a/tests/test_cli.py
++++ b/tests/test_cli.py
+@@ -1607,6 +1607,25 @@ class TestSources(LookasideCacheMock, CliTestCase):
+     def test_unused_sources_are_not_downloaded(self):
+         self._upload_unused()
+ 
++        cli_cmd = ['rpkg', '--path', self.cloned_repo_path, 'sources']
++        with patch('sys.argv', new=cli_cmd):
++            with patch('pyrpkg.Commands.rpmdefines',
++                        new=['--define', '_sourcedir %s' % self.cloned_repo_path]):
++                cli = self.new_cli()
++                with patch('pyrpkg.lookaside.CGILookasideCache.download',
++                           new=self.lookasidecache_download):
++                    cli.sources()
++
++        path = os.path.join(self.cloned_repo_path, 'unused.patch')
++        self.assertFalse(os.path.exists(path))
++
++    @patch('pyrpkg.Commands.load_rpmdefines')
++    def test_download_sources_including_unused(self, rpmdefines):
++        self._upload_unused()
++        # SpecFile parsing executes 'rpmspec', that needs '--define' arguments from rpmdefines
++        # when rpmdefines raises eception, SpecFile parsing fails --> all sources are downloaded.
++        rpmdefines.side_effect = rpkgError
++
+         cli_cmd = ['rpkg', '--path', self.cloned_repo_path, 'sources']
+         with patch('sys.argv', new=cli_cmd):
+             cli = self.new_cli()
+@@ -1615,7 +1634,7 @@ class TestSources(LookasideCacheMock, CliTestCase):
+                 cli.sources()
+ 
+         path = os.path.join(self.cloned_repo_path, 'unused.patch')
+-        self.assertFalse(os.path.exists(path))
++        self.assertTrue(os.path.exists(path))
+ 
+     def test_force_option_downloads_unused_sources(self):
+         self._upload_unused()
+diff --git a/tests/test_spec.py b/tests/test_spec.py
+index eefc475..0c7907a 100644
+--- a/tests/test_spec.py
++++ b/tests/test_spec.py
+@@ -10,6 +10,10 @@ from pyrpkg.errors import rpkgError
+ class SpecFileTestCase(unittest.TestCase):
+     def setUp(self):
+         self.workdir = tempfile.mkdtemp(prefix='rpkg-tests.')
++        self.rpmdefines = ["--define", "_sourcedir %s" % self.workdir,
++                           "--define", "_specdir %s" % self.workdir,
++                           "--define", "_builddir %s" % self.workdir,
++                           "--eval", "%%undefine rhel"]
+         self.specfile = os.path.join(self.workdir, self._testMethodName)
+ 
+         # Write common header
+@@ -43,7 +47,7 @@ class SpecFileTestCase(unittest.TestCase):
+             "PAtch999: https://remote.patch-sourcce.org/another-patch.bz2\n")
+         spec_fd.close()
+ 
+-        s = spec.SpecFile(self.specfile, self.workdir)
++        s = spec.SpecFile(self.specfile, self.rpmdefines)
+         actual = s.sources
+         expected = [
+             "tarball.tar.gz",
+@@ -65,4 +69,4 @@ class SpecFileTestCase(unittest.TestCase):
+         self.assertRaises(rpkgError,
+                           spec.SpecFile,
+                           self.specfile,
+-                          self.workdir)
++                          self.rpmdefines)
+-- 
+2.40.0
+

diff --git a/0021-Do-not-require-sources-file-for-all-namespaces.patch b/0021-Do-not-require-sources-file-for-all-namespaces.patch
new file mode 100644
index 0000000..a4c71aa
--- /dev/null
+++ b/0021-Do-not-require-sources-file-for-all-namespaces.patch
@@ -0,0 +1,60 @@
+From 079a64dde258f45e26fe35de86b1a0915f4973cd Mon Sep 17 00:00:00 2001
+From: Ondrej Nosek <onosek@redhat.com>
+Date: Thu, 27 Apr 2023 23:05:48 +0200
+Subject: [PATCH 2/2] Do not require 'sources' file for all namespaces
+
+Requirement for 'sources' file for all layouts except the RetiredLayout
+(and thus all namespaces) was too restrictive and unexpected.
+Partially reverts the commit 1108810bdefd0d880517b274acd6a3bd0d4156e0.
+
+Fixes: #684
+JIRA: RHELCMP-11529
+
+Signed-off-by: Ondrej Nosek <onosek@redhat.com>
+---
+ pyrpkg/__init__.py | 2 --
+ pyrpkg/cli.py      | 1 -
+ tests/test_cli.py  | 2 +-
+ 3 files changed, 1 insertion(+), 4 deletions(-)
+
+diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py
+index 817ef33..11b8dae 100644
+--- a/pyrpkg/__init__.py
++++ b/pyrpkg/__init__.py
+@@ -1168,8 +1168,6 @@ class Commands(object):
+ 
+     @property
+     def sources_filename(self):
+-        if self.layout is None or isinstance(self.layout, layout.IncompleteLayout):
+-            raise rpkgError('Spec file is not available')
+         if isinstance(self.layout, layout.RetiredLayout):
+             raise rpkgError('This package or module is retired. The action has stopped.')
+         return os.path.join(
+diff --git a/pyrpkg/cli.py b/pyrpkg/cli.py
+index a1f3f44..dc1eb4e 100644
+--- a/pyrpkg/cli.py
++++ b/pyrpkg/cli.py
+@@ -2375,7 +2375,6 @@ class cliClient(object):
+ 
+     def import_srpm(self):
+         uploadfiles = self.cmd.import_srpm(self.args.srpm)
+-        self.load_cmd()  # to reload layouts - because a specfile could appear during import
+         if uploadfiles:
+             try:
+                 self.cmd.upload(uploadfiles, replace=True, offline=self.args.offline)
+diff --git a/tests/test_cli.py b/tests/test_cli.py
+index 58df047..6e4ec6a 100644
+--- a/tests/test_cli.py
++++ b/tests/test_cli.py
+@@ -1610,7 +1610,7 @@ class TestSources(LookasideCacheMock, CliTestCase):
+         cli_cmd = ['rpkg', '--path', self.cloned_repo_path, 'sources']
+         with patch('sys.argv', new=cli_cmd):
+             with patch('pyrpkg.Commands.rpmdefines',
+-                        new=['--define', '_sourcedir %s' % self.cloned_repo_path]):
++                       new=['--define', '_sourcedir %s' % self.cloned_repo_path]):
+                 cli = self.new_cli()
+                 with patch('pyrpkg.lookaside.CGILookasideCache.download',
+                            new=self.lookasidecache_download):
+-- 
+2.40.0
+

diff --git a/rpkg.spec b/rpkg.spec
index 60d99d1..17e44ee 100644
--- a/rpkg.spec
+++ b/rpkg.spec
@@ -1,6 +1,6 @@
 Name:           rpkg
 Version:        1.66
-Release:        6%{?dist}
+Release:        7%{?dist}
 
 Summary:        Python library for interacting with rpm+git
 License:        GPLv2+ and LGPLv2
@@ -53,6 +53,8 @@ Patch16:        0016-Check-remote-file-with-correct-hash.patch
 Patch17:        0017-Allow-empty-commits-when-uses_rpmautospec.patch
 Patch18:        0018-Config-file-option-to-skip-the-hook-script-creation.patch
 Patch19:        0019-Pre-push-hook-won-t-check-private-branches.patch
+Patch20:        0020-Use-release-s-rpmdefines-in-unused-sources-check.patch
+Patch21:        0021-Do-not-require-sources-file-for-all-namespaces.patch
 
 %description
 Python library for interacting with rpm+git
@@ -269,6 +271,10 @@ example_cli_dir=$RPM_BUILD_ROOT%{_datadir}/%{name}/examples/cli
 
 
 %changelog
+* Fri Apr 28 2023 Ondřej Nosek <onosek@redhat.com> - 1.66-7
+- Patch: Do not require 'sources' file for all namespaces
+- Use release's rpmdefines in unused sources check
+
 * Tue Apr 18 2023 Ondřej Nosek <onosek@redhat.com> - 1.66-6
 - Patch: Pre-push hook won't check private branches
 - Patch: Config file option to skip the hook script creation

^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-08-10 21:44 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-08-10 21:44 [rpms/rpkg] 1.70-1: A few patches: 
  -- strict thread matches above, loose matches on Subject: below --
2026-08-10 21:44 
2026-08-10 21:44 
2026-08-10 21:44 
2026-08-10 21:44 
2026-08-10 21:44 

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