diff --git a/0002-Protect-against-decoding-errors-with-subprocess-text.patch b/0002-Protect-against-decoding-errors-with-subprocess-text.patch deleted file mode 100644 index 070a45e1..00000000 --- a/0002-Protect-against-decoding-errors-with-subprocess-text.patch +++ /dev/null @@ -1,776 +0,0 @@ -From 1f4935685308a57bfcb149b9384b2f5984692075 Mon Sep 17 00:00:00 2001 -From: Adam Williamson -Date: Wed, 15 Jan 2025 11:00:33 -0800 -Subject: [PATCH 2/2] Protect against decoding errors with subprocess text mode - -All these are calling subprocess in 'text mode', where it will -try to decode stdout/stderr using the default encoding (utf-8 -for us). If it doesn't decode, subprocess will raise an exception -and kobo doesn't handle it, it just passes it along to us, so -things blow up - see https://pagure.io/releng/issue/12474 . To -avoid this, let's set `errors="replace"`, which tells the decoder -to replace invalid data with ? characters. This way we should get -as much of the output as can be read, and no crashes. - -We also replace `universal_newlines=True` with `text=True` as -the latter is shorter, clearer, and what Python 3 subprocess -wants us to use, it considers `universal_newlines` to just be -a backwards-compatibility thing - "The universal_newlines argument -is equivalent to text and is provided for backwards compatibility" - -Signed-off-by: Adam Williamson ---- - pungi/__init__.py | 5 ++- - pungi/notifier.py | 3 +- - pungi/ostree/tree.py | 6 ++- - pungi/phases/ostree_container.py | 2 +- - pungi/util.py | 11 ++++-- - pungi/wrappers/iso.py | 8 ++-- - pungi/wrappers/kojiwrapper.py | 11 ++++-- - pungi/wrappers/scm.py | 3 +- - pungi_utils/patch_iso.py | 5 ++- - pungi_utils/unified_isos.py | 3 +- - tests/test_iso_wrapper.py | 6 ++- - tests/test_koji_wrapper.py | 66 +++++++++++++++++++++----------- - tests/test_notifier.py | 3 +- - tests/test_ostree_script.py | 6 ++- - tests/test_patch_iso.py | 2 +- - tests/test_unified_isos.py | 2 +- - tests/test_util.py | 60 +++++++++++++++++++---------- - 17 files changed, 132 insertions(+), 70 deletions(-) - -diff --git a/pungi/__init__.py b/pungi/__init__.py -index d4a48dca..8b672a72 100644 ---- a/pungi/__init__.py -+++ b/pungi/__init__.py -@@ -16,7 +16,8 @@ def get_full_version(): - proc = subprocess.Popen( - ["git", "--git-dir=%s/.git" % location, "describe", "--tags"], - stdout=subprocess.PIPE, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - output, _ = proc.communicate() - return re.sub(r"-1.fc\d\d?", "", output.strip().replace("pungi-", "")) -@@ -24,7 +25,7 @@ def get_full_version(): - import subprocess - - proc = subprocess.Popen( -- ["rpm", "-q", "pungi"], stdout=subprocess.PIPE, universal_newlines=True -+ ["rpm", "-q", "pungi"], stdout=subprocess.PIPE, text=True, errors="replace" - ) - (output, err) = proc.communicate() - if not err: -diff --git a/pungi/notifier.py b/pungi/notifier.py -index bef2ae63..a42c6184 100644 ---- a/pungi/notifier.py -+++ b/pungi/notifier.py -@@ -104,7 +104,8 @@ class PungiNotifier(object): - workdir=workdir, - return_stdout=False, - show_cmd=True, -- universal_newlines=True, -+ text=True, -+ errors="replace", - logfile=logfile, - ) - if ret != 0: -diff --git a/pungi/ostree/tree.py b/pungi/ostree/tree.py -index 1ba138b3..5da6fd7a 100644 ---- a/pungi/ostree/tree.py -+++ b/pungi/ostree/tree.py -@@ -64,7 +64,8 @@ class Tree(OSTree): - show_cmd=True, - stdout=True, - logfile=log_file, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - finally: - os.umask(oldumask) -@@ -77,7 +78,8 @@ class Tree(OSTree): - show_cmd=True, - stdout=True, - logfile=log_file, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - - def _update_ref(self): -diff --git a/pungi/phases/ostree_container.py b/pungi/phases/ostree_container.py -index c0179620..b752d16c 100644 ---- a/pungi/phases/ostree_container.py -+++ b/pungi/phases/ostree_container.py -@@ -139,7 +139,7 @@ class OSTreeContainerThread(WorkerThread): - "--version=%s" % version, - ] - -- _, runroot_script = shortcuts.run(cmd, universal_newlines=True) -+ _, runroot_script = shortcuts.run(cmd, text=True, errors="replace") - - default_packages = ["ostree", "rpm-ostree", "selinux-policy-targeted"] - additional_packages = config.get("runroot_packages", []) -diff --git a/pungi/util.py b/pungi/util.py -index fccdb228..4cde13d6 100644 ---- a/pungi/util.py -+++ b/pungi/util.py -@@ -652,7 +652,11 @@ def run_unmount_cmd(cmd, max_retries=10, path=None, logger=None): - """ - for i in range(max_retries): - proc = subprocess.Popen( -- cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True -+ cmd, -+ stdout=subprocess.PIPE, -+ stderr=subprocess.PIPE, -+ text=True, -+ errors="replace", - ) - out, err = proc.communicate() - if proc.returncode == 0: -@@ -674,7 +678,8 @@ def run_unmount_cmd(cmd, max_retries=10, path=None, logger=None): - c, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - out, _ = proc.communicate() - logger.debug( -@@ -879,7 +884,7 @@ def git_ls_remote(baseurl, ref, credential_helper=None): - if credential_helper: - cmd.extend(["-c", "credential.useHttpPath=true"]) - cmd.extend(["-c", "credential.helper=%s" % credential_helper]) -- return run(cmd + ["ls-remote", baseurl, ref], universal_newlines=True) -+ return run(cmd + ["ls-remote", baseurl, ref], text=True, errors="replace") - - - def get_tz_offset(): -diff --git a/pungi/wrappers/iso.py b/pungi/wrappers/iso.py -index 5a2533f8..2ca7a8db 100644 ---- a/pungi/wrappers/iso.py -+++ b/pungi/wrappers/iso.py -@@ -227,7 +227,7 @@ def get_checkisomd5_cmd(iso_path, just_print=False): - - def get_checkisomd5_data(iso_path, logger=None): - cmd = get_checkisomd5_cmd(iso_path, just_print=True) -- retcode, output = run(cmd, universal_newlines=True) -+ retcode, output = run(cmd, text=True, errors="replace") - items = [line.strip().rsplit(":", 1) for line in output.splitlines()] - items = dict([(k, v.strip()) for k, v in items]) - md5 = items.get(iso_path, "") -@@ -283,13 +283,13 @@ def get_manifest_cmd(iso_name, xorriso=False, output_file=None): - def get_volume_id(path, xorriso=False): - if xorriso: - cmd = ["xorriso", "-indev", path] -- retcode, output = run(cmd, universal_newlines=True) -+ retcode, output = run(cmd, text=True, errors="replace") - for line in output.splitlines(): - if line.startswith("Volume id"): - return line.split("'")[1] - else: - cmd = ["isoinfo", "-d", "-i", path] -- retcode, output = run(cmd, universal_newlines=True) -+ retcode, output = run(cmd, text=True, errors="replace") - - for line in output.splitlines(): - line = line.strip() -@@ -500,7 +500,7 @@ def mount(image, logger=None, use_guestmount=True): - else: - env = {} - cmd = ["mount", "-o", "loop", image, mount_dir] -- ret, out = run(cmd, env=env, can_fail=True, universal_newlines=True) -+ ret, out = run(cmd, env=env, can_fail=True, text=True, errors="replace") - if ret != 0: - # The mount command failed, something is wrong. - # Log the output and raise an exception. -diff --git a/pungi/wrappers/kojiwrapper.py b/pungi/wrappers/kojiwrapper.py -index 83c878a6..fecce1e1 100644 ---- a/pungi/wrappers/kojiwrapper.py -+++ b/pungi/wrappers/kojiwrapper.py -@@ -294,7 +294,8 @@ class KojiWrapper(object): - show_cmd=True, - env=env, - buffer_size=-1, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - - # Look for first line that contains only a number. This is the ID of -@@ -430,7 +431,7 @@ class KojiWrapper(object): - - while True: - retcode, output = run( -- cmd, can_fail=True, logfile=logfile, universal_newlines=True -+ cmd, can_fail=True, logfile=logfile, text=True, errors="replace" - ) - - if retcode == 0 or not ( -@@ -463,7 +464,8 @@ class KojiWrapper(object): - logfile=log_file, - env=env, - buffer_size=-1, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - - match = re.search(r"Created task: (\d+)", output) -@@ -808,7 +810,8 @@ def get_buildroot_rpms(compose, task_id): - # local - retcode, output = run( - "rpm -qa --qf='%{name}-%{version}-%{release}.%{arch}\n'", -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - for i in output.splitlines(): - if not i: -diff --git a/pungi/wrappers/scm.py b/pungi/wrappers/scm.py -index 9b4bc994..cfdd2907 100644 ---- a/pungi/wrappers/scm.py -+++ b/pungi/wrappers/scm.py -@@ -56,7 +56,8 @@ class ScmBase(kobo.log.LoggingBase): - workdir=cwd, - can_fail=True, - stdin_data="", -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - if retcode != 0: - self.log_error("Output was: %r" % output) -diff --git a/pungi_utils/patch_iso.py b/pungi_utils/patch_iso.py -index 469736dd..13dddf58 100644 ---- a/pungi_utils/patch_iso.py -+++ b/pungi_utils/patch_iso.py -@@ -25,7 +25,7 @@ from pungi.wrappers import iso - - def sh(log, cmd, *args, **kwargs): - log.info("Running: %s", " ".join(shlex.quote(x) for x in cmd)) -- ret, out = shortcuts.run(cmd, *args, universal_newlines=True, **kwargs) -+ ret, out = shortcuts.run(cmd, *args, text=True, errors="replace", **kwargs) - if out: - log.debug("%s", out) - return ret, out -@@ -35,7 +35,8 @@ def get_lorax_dir(default="/usr/share/lorax"): - try: - _, out = shortcuts.run( - ["python3", "-c" "import pylorax; print(pylorax.find_templates())"], -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - return out.strip() - except Exception: -diff --git a/pungi_utils/unified_isos.py b/pungi_utils/unified_isos.py -index 517921b7..a692e3b0 100644 ---- a/pungi_utils/unified_isos.py -+++ b/pungi_utils/unified_isos.py -@@ -394,7 +394,8 @@ class UnifiedISO(object): - iso.get_mkisofs_cmd( - iso_path, [source_dir], volid=volid, exclude=["./lost+found"] - ), -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - - # implant MD5 -diff --git a/tests/test_iso_wrapper.py b/tests/test_iso_wrapper.py -index 28ea976e..c7770413 100644 ---- a/tests/test_iso_wrapper.py -+++ b/tests/test_iso_wrapper.py -@@ -63,7 +63,8 @@ class TestIsoUtils(unittest.TestCase): - [ - mock.call( - ["/usr/bin/checkisomd5", "--md5sumonly", "dummy.iso"], -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - ], - ) -@@ -79,7 +80,8 @@ class TestIsoUtils(unittest.TestCase): - [ - mock.call( - ["/usr/bin/checkisomd5", "--md5sumonly", "dummy.iso"], -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - ], - ) -diff --git a/tests/test_koji_wrapper.py b/tests/test_koji_wrapper.py -index 9e0a5c17..e06d19c5 100644 ---- a/tests/test_koji_wrapper.py -+++ b/tests/test_koji_wrapper.py -@@ -529,7 +529,8 @@ class RunrootKojiWrapperTest(KojiWrapperBaseTestCase): - buffer_size=-1, - logfile=None, - show_cmd=True, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - ], - ) -@@ -558,7 +559,8 @@ class RunrootKojiWrapperTest(KojiWrapperBaseTestCase): - buffer_size=-1, - logfile=None, - show_cmd=True, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - ], - ) -@@ -582,7 +584,8 @@ class RunrootKojiWrapperTest(KojiWrapperBaseTestCase): - buffer_size=-1, - logfile=None, - show_cmd=True, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - ], - ) -@@ -615,7 +618,8 @@ class RunrootKojiWrapperTest(KojiWrapperBaseTestCase): - buffer_size=-1, - logfile=None, - show_cmd=True, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - ], - ) -@@ -641,7 +645,8 @@ class RunBlockingCmdTest(KojiWrapperBaseTestCase): - show_cmd=True, - env={"FOO": "BAR", "PYTHONUNBUFFERED": "1"}, - buffer_size=-1, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - ], - ) -@@ -671,7 +676,8 @@ class RunBlockingCmdTest(KojiWrapperBaseTestCase): - "PYTHONUNBUFFERED": "1", - }, - buffer_size=-1, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - ], - ) -@@ -694,7 +700,8 @@ class RunBlockingCmdTest(KojiWrapperBaseTestCase): - logfile="logfile", - env={"FOO": "BAR", "PYTHONUNBUFFERED": "1"}, - buffer_size=-1, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - ], - ) -@@ -717,7 +724,8 @@ class RunBlockingCmdTest(KojiWrapperBaseTestCase): - logfile=None, - env={"FOO": "BAR", "PYTHONUNBUFFERED": "1"}, - buffer_size=-1, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - ], - ) -@@ -740,7 +748,8 @@ class RunBlockingCmdTest(KojiWrapperBaseTestCase): - logfile=None, - env={"FOO": "BAR", "PYTHONUNBUFFERED": "1"}, - buffer_size=-1, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - ], - ) -@@ -765,13 +774,15 @@ class RunBlockingCmdTest(KojiWrapperBaseTestCase): - logfile=None, - env={"FOO": "BAR", "PYTHONUNBUFFERED": "1"}, - buffer_size=-1, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ), - mock.call( - ["koji", "--profile=custom-koji", "watch-task", "1234"], - can_fail=True, - logfile=None, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ), - ], - ) -@@ -795,13 +806,15 @@ class RunBlockingCmdTest(KojiWrapperBaseTestCase): - logfile=None, - env={"FOO": "BAR", "PYTHONUNBUFFERED": "1"}, - buffer_size=-1, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ), - mock.call( - ["koji", "--profile=custom-koji", "watch-task", "1234"], - can_fail=True, - logfile=None, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ), - ], - ) -@@ -826,25 +839,29 @@ class RunBlockingCmdTest(KojiWrapperBaseTestCase): - logfile=None, - env={"FOO": "BAR", "PYTHONUNBUFFERED": "1"}, - buffer_size=-1, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ), - mock.call( - ["koji", "--profile=custom-koji", "watch-task", "1234"], - can_fail=True, - logfile=None, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ), - mock.call( - ["koji", "--profile=custom-koji", "watch-task", "1234"], - can_fail=True, - logfile=None, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ), - mock.call( - ["koji", "--profile=custom-koji", "watch-task", "1234"], - can_fail=True, - logfile=None, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ), - ], - ) -@@ -870,19 +887,22 @@ class RunBlockingCmdTest(KojiWrapperBaseTestCase): - logfile=None, - env={"FOO": "BAR", "PYTHONUNBUFFERED": "1"}, - buffer_size=-1, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ), - mock.call( - ["koji", "--profile=custom-koji", "watch-task", "1234"], - can_fail=True, - logfile=None, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ), - mock.call( - ["koji", "--profile=custom-koji", "watch-task", "1234"], - can_fail=True, - logfile=None, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ), - ], - ) -@@ -907,13 +927,15 @@ class RunBlockingCmdTest(KojiWrapperBaseTestCase): - logfile=None, - env={"FOO": "BAR", "PYTHONUNBUFFERED": "1"}, - buffer_size=-1, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ), - mock.call( - ["koji", "--profile=custom-koji", "watch-task", "1234"], - can_fail=True, - logfile=None, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ), - ], - ) -diff --git a/tests/test_notifier.py b/tests/test_notifier.py -index e5584cc6..53ea4c94 100644 ---- a/tests/test_notifier.py -+++ b/tests/test_notifier.py -@@ -70,7 +70,8 @@ class TestNotifier(unittest.TestCase): - can_fail=True, - return_stdout=False, - workdir=None, -- universal_newlines=True, -+ text=True, -+ errors="replace", - show_cmd=True, - logfile=self.logfile, - ) -diff --git a/tests/test_ostree_script.py b/tests/test_ostree_script.py -index 6276f729..b2f37a37 100644 ---- a/tests/test_ostree_script.py -+++ b/tests/test_ostree_script.py -@@ -67,7 +67,8 @@ class OstreeTreeScriptTest(helpers.PungiTestCase): - logfile=self.topdir + "/logs/Atomic/create-ostree-repo.log", - show_cmd=True, - stdout=True, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - ] - + extra_calls, -@@ -136,7 +137,8 @@ class OstreeTreeScriptTest(helpers.PungiTestCase): - logfile=self.topdir + "/logs/Atomic/ostree-summary.log", - show_cmd=True, - stdout=True, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - ], - ) -diff --git a/tests/test_patch_iso.py b/tests/test_patch_iso.py -index 87e052d0..4ba10206 100644 ---- a/tests/test_patch_iso.py -+++ b/tests/test_patch_iso.py -@@ -34,7 +34,7 @@ class TestSh(unittest.TestCase): - patch_iso.sh(log, ["ls"], foo="bar") - self.assertEqual( - mock_run.call_args_list, -- [mock.call(["ls"], foo="bar", universal_newlines=True)], -+ [mock.call(["ls"], foo="bar", text=True, errors="replace")], - ) - self.assertEqual(log.info.call_args_list, [mock.call("Running: %s", "ls")]) - self.assertEqual(log.debug.call_args_list, [mock.call("%s", "ok")]) -diff --git a/tests/test_unified_isos.py b/tests/test_unified_isos.py -index bf095d9c..134306e1 100755 ---- a/tests/test_unified_isos.py -+++ b/tests/test_unified_isos.py -@@ -610,7 +610,7 @@ class TestCreateiso(PungiTestCase): - self.assertEqual( - run.mock_calls, - [ -- mock.call(self.mkisofs_cmd, universal_newlines=True), -+ mock.call(self.mkisofs_cmd, text=True, errors="replace"), - mock.call(iso.get_implantisomd5_cmd.return_value), - mock.call(iso.get_manifest_cmd.return_value), - ] -diff --git a/tests/test_util.py b/tests/test_util.py -index cf281c8a..00f875fd 100644 ---- a/tests/test_util.py -+++ b/tests/test_util.py -@@ -25,7 +25,8 @@ class TestGitRefResolver(unittest.TestCase): - self.assertEqual(url, "https://git.example.com/repo.git?somedir#CAFEBABE") - run.assert_called_once_with( - ["git", "ls-remote", "https://git.example.com/repo.git", "HEAD"], -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - - @mock.patch("pungi.util.run") -@@ -39,7 +40,8 @@ class TestGitRefResolver(unittest.TestCase): - self.assertEqual(url, "https://git.example.com/repo.git?somedir#CAFEBABE") - run.assert_called_once_with( - GIT_WITH_CREDS + ["ls-remote", "https://git.example.com/repo.git", "HEAD"], -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - - @mock.patch("pungi.util.run") -@@ -53,7 +55,8 @@ class TestGitRefResolver(unittest.TestCase): - self.assertEqual(url, "https://git.example.com/repo.git?somedir#CAFEBABE") - run.assert_called_once_with( - ["git", "ls-remote", "https://git.example.com/repo.git", "refs/heads/f24"], -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - - def test_resolve_ref_with_commit_id(self): -@@ -72,7 +75,8 @@ class TestGitRefResolver(unittest.TestCase): - self.assertEqual(ref, "CAFEBABE") - run.assert_called_once_with( - ["git", "ls-remote", "https://git.example.com/repo.git", "master"], -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - - @mock.patch("pungi.util.run") -@@ -84,7 +88,8 @@ class TestGitRefResolver(unittest.TestCase): - self.assertEqual(ref, "CAFEBABE") - run.assert_called_once_with( - ["git", "ls-remote", "https://git.example.com/repo.git", "HEAD"], -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - - @mock.patch("pungi.util.run") -@@ -110,7 +115,8 @@ class TestGitRefResolver(unittest.TestCase): - - run.assert_called_once_with( - ["git", "ls-remote", "https://git.example.com/repo.git", "HEAD"], -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - - @mock.patch("pungi.util.run") -@@ -121,7 +127,8 @@ class TestGitRefResolver(unittest.TestCase): - - run.assert_called_once_with( - ["git", "ls-remote", "https://git.example.com/repo.git", "HEAD"], -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - self.assertEqual(url, "https://git.example.com/repo.git?#CAFEBABE") - -@@ -133,7 +140,8 @@ class TestGitRefResolver(unittest.TestCase): - - run.assert_called_once_with( - ["git", "ls-remote", "https://git.example.com/repo.git", "HEAD"], -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - self.assertEqual(url, "git+https://git.example.com/repo.git#CAFEBABE") - -@@ -153,7 +161,8 @@ class TestGitRefResolver(unittest.TestCase): - "https://git.example.com/repo.git", - "refs/heads/my-branch", - ], -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - self.assertIn("ref does not exist in remote repo", str(ctx.exception)) - -@@ -171,7 +180,8 @@ class TestGitRefResolver(unittest.TestCase): - [ - mock.call( - ["git", "ls-remote", "https://git.example.com/repo.git", "HEAD"], -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - ] - * 2, -@@ -600,7 +610,8 @@ class TestUnmountCmd(unittest.TestCase): - cmd, - stderr=subprocess.PIPE, - stdout=subprocess.PIPE, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - ], - ) -@@ -621,7 +632,8 @@ class TestUnmountCmd(unittest.TestCase): - cmd, - stderr=subprocess.PIPE, - stdout=subprocess.PIPE, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - ], - ) -@@ -643,7 +655,8 @@ class TestUnmountCmd(unittest.TestCase): - cmd, - stderr=subprocess.PIPE, - stdout=subprocess.PIPE, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - ] - * 3, -@@ -668,7 +681,8 @@ class TestUnmountCmd(unittest.TestCase): - cmd, - stderr=subprocess.PIPE, - stdout=subprocess.PIPE, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ) - ] - * 3, -@@ -707,37 +721,43 @@ class TestUnmountCmd(unittest.TestCase): - cmd, - stderr=subprocess.PIPE, - stdout=subprocess.PIPE, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ), - mock.call( - cmd, - stderr=subprocess.PIPE, - stdout=subprocess.PIPE, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ), - mock.call( - cmd, - stderr=subprocess.PIPE, - stdout=subprocess.PIPE, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ), - mock.call( - ["ls", "-lA", "/path"], - stderr=subprocess.STDOUT, - stdout=subprocess.PIPE, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ), - mock.call( - ["fuser", "-vm", "/path"], - stderr=subprocess.STDOUT, - stdout=subprocess.PIPE, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ), - mock.call( - ["lsof", "+D", "/path"], - stderr=subprocess.STDOUT, - stdout=subprocess.PIPE, -- universal_newlines=True, -+ text=True, -+ errors="replace", - ), - ] - self.assertEqual(mockPopen.call_args_list, expected) --- -2.47.1 - diff --git a/1810.patch b/1810.patch deleted file mode 100644 index 5eba910a..00000000 --- a/1810.patch +++ /dev/null @@ -1,91 +0,0 @@ -From 3cb8992d56f2cee8a7cb151253125e30931ccd6d Mon Sep 17 00:00:00 2001 -From: Adam Williamson -Date: Dec 12 2024 01:52:40 +0000 -Subject: Use new container and bootable-container productmd types - - -In https://github.com/release-engineering/productmd/pull/181 I -added new `bootable-container` and `container` types to -productmd. This makes pungi always use the bootable-container -type for ostree_container images (previously 'ociarchive'), and -default to using the container type for Kiwi-built oci.tar.xz -container images (previously 'docker'). - -This is a significant change for anything that relies on -productmd/fedfind conventions to 'identify' images, as these -images will now have a different identity. But I think it's a -valuable improvement in their identities. 'ociarchive' never made -any sense as an image 'type' - it's a format - and 'docker' -wasn't a very good type for images that are explicitly OCI -container images, not Docker-native ones. We also can now easily -distinguish between 'regular' container images and ones that are -intended to be bootable. - -Signed-off-by: Adam Williamson - ---- - -diff --git a/pungi/phases/kiwibuild.py b/pungi/phases/kiwibuild.py -index 400ea6a..9b75dd7 100644 ---- a/pungi/phases/kiwibuild.py -+++ b/pungi/phases/kiwibuild.py -@@ -25,6 +25,7 @@ KIWIEXTENSIONS = [ - ("fex", ["squashfs.xz"], "squashfs.xz"), - ("fex", ["squashfs.gz"], "squashfs.gz"), - ("fex", ["squashfs"], "squashfs"), -+ ("container", ["oci.tar.xz"], "tar.xz"), - ] - - -@@ -242,13 +243,15 @@ class RunKiwiBuildThread(WorkerThread): - - - def _find_type_and_format(path): -- for type_, suffixes in EXTENSIONS.items(): -- for suffix in suffixes: -- if path.endswith(suffix): -- return type_, suffix - # these are our kiwi-exclusive mappings for images whose extensions -- # aren't quite the same as imagefactory -+ # aren't quite the same as imagefactory. they come first as we -+ # want our oci.tar.xz mapping to win over the tar.xz one in -+ # EXTENSIONS - for type_, suffixes, format_ in KIWIEXTENSIONS: - if any(path.endswith(suffix) for suffix in suffixes): - return type_, format_ -+ for type_, suffixes in EXTENSIONS.items(): -+ for suffix in suffixes: -+ if path.endswith(suffix): -+ return type_, suffix - return None, None -diff --git a/pungi/phases/ostree_container.py b/pungi/phases/ostree_container.py -index c50633d..c017962 100644 ---- a/pungi/phases/ostree_container.py -+++ b/pungi/phases/ostree_container.py -@@ -164,9 +164,9 @@ class OSTreeContainerThread(WorkerThread): - # Update image manifest - img = Image(compose.im) - -- # Get the manifest type from the config if supplied, otherwise we -- # determine the manifest type based on the koji output -- img.type = "ociarchive" -+ # these are hardcoded as they should always be correct, we -+ # could potentially allow overriding them via config though -+ img.type = "bootable-container" - img.format = "ociarchive" - img.path = os.path.relpath(fullpath, compose.paths.compose.topdir()) - img.mtime = util.get_mtime(fullpath) -diff --git a/setup.py b/setup.py -index fd249c0..839400b 100755 ---- a/setup.py -+++ b/setup.py -@@ -56,7 +56,7 @@ setup( - "jsonschema", - "kobo", - "lxml", -- "productmd>=1.23", -+ "productmd>=1.43", - "dogpile.cache", - ], - extras_require={':python_version=="2.7"': ["enum34", "lockfile"]}, - diff --git a/pungi.spec b/pungi.spec index e391a665..2b5f0966 100644 --- a/pungi.spec +++ b/pungi.spec @@ -1,20 +1,13 @@ %{?python_enable_dependency_generator} Name: pungi -Version: 4.8.0 -Release: 3%{?dist}.alma.1 +Version: 4.9.0 +Release: 1%{?dist}.alma.1 Summary: Distribution compose tool License: GPL-2.0-only URL: https://pagure.io/pungi Source0: %{name}-%{version}.tar.bz2 -# https://pagure.io/pungi/pull-request/1810 -# Use container and bootable-container productmd types -Patch: 1810.patch -# https://pagure.io/pungi/pull-request/1812 -# https://pagure.io/releng/issue/12474 -# Avoid crashing if command output cannot be decoded as utf-8 -Patch: 0002-Protect-against-decoding-errors-with-subprocess-text.patch BuildRequires: make BuildRequires: python3-pytest @@ -179,6 +172,16 @@ gzip _build/man/pungi.1 %{_bindir}/%{name}-cache-cleanup %changelog +* Fri Feb 14 2025 Lubomír Sedlář - 4.9.0-1 +- buildinstall: Add support for rootfs-type lorax option (lsedlar) +- scm: Stop trying to download src arch (lsedlar) +- extra_isos: Provide arch to extra files getter (lsedlar) +- Move temporary buildinstall download to work/ (lsedlar) +- Download extra files from container registry (lsedlar) +- Remove python 2.7 dependencies from setup.py (lsedlar) +- util: Drop dead code (lsedlar) +- Directly import mock from unittest (lsedlar) + * Thu Jan 16 2025 Adam Williamson - 4.8.0-3 - Backport PR #1812 to fix crash on subprocess unicode decode error diff --git a/sources b/sources index 3de551b2..ea2f2019 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (pungi-4.8.0.tar.bz2) = 8ba996b2aeed47ef3b155fc3523519a5570fc191b0a4d779afa3ec3a0fb028ea6a21804ab195ef11eb97010042007f4aa483de51c36568653c8a2fe178b7b4ef +SHA512 (pungi-4.9.0.tar.bz2) = 43a21594d36e49b81aa600f5194080cf491f429cad2f07934524a3e0d1cdcfeff3eeb3740aa3454c8889d50a46e113556eb3b90af69ce83ee654cb2e80b03469