I initially reported this in bugzilla against fedpkg, but I suspect the issue, and thus the fix, really lives with rpkg itself. Also, in debugging the first issue I discovered more problems with 'patch' that make me think it hasn't worked in a long time, nor has anyone been using it to notice it's broken.
The switch to fedpkg prep / fedpkg local extracting and building package sources inside a %{name}-%{version}-build/%{name}-%{version}/ subdirectory broke the fedpkg patch command, which (as implemented in pyrpkg) expects there to be a top-level %{name}-%{version} directory next to the spec file.
fedpkg prep
fedpkg local
%{name}-%{version}-build/%{name}-%{version}/
fedpkg patch
%{name}-%{version}
To Reproduce: Start with a fedpkg clone of any package (let's use fedpkg itself...), and attempt to create a patch using a fake modified setup.py.edited:
setup.py.edited
fedpkg clone fedpkg cd fedpkg fedpkg prep # creates the directory fedpkg-1.46-build/fedpkg-1.46/ cp fedpkg-1.46-build/fedpkg-1.46/setup.py \ fedpkg-1.46-build/fedpkg-1.46/setup.py.edited fedpkg patch edited
This will output:
Could not execute patch: Expanded source dir not found!
Because the fedpkg patch command still expects the extracted source to be in ./fedpkg-1.46/, not ./fedpkg-1.46-build/fedpkg-1.46.
./fedpkg-1.46/
./fedpkg-1.46-build/fedpkg-1.46
So, let's move it there:
mv fedpkg-1.46-build/fedpkg-1.46 . fedpkg patch edited
bytes
This time, we get the message:
Could not execute patch: write() argument must be str, not bytes
If we run with debugging (fedpkg -d -v -v patch edited), we get more details:
fedpkg -d -v -v patch edited
Creating repo object from /tmp/fedpkg Initiating a koji session to https://koji.fedoraproject.org/kojihub Running gendiff fedpkg-1.46 .edited Could not execute patch: write() argument must be str, not bytes Traceback (most recent call last): File "/usr/bin/fedpkg", line 33, in <module> sys.exit(load_entry_point('fedpkg==1.46', 'console_scripts', 'fedpkg')()) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^ File "/usr/lib/python3.13/site-packages/fedpkg/__main__.py", line 84, in main sys.exit(client.args.command()) ~~~~~~~~~~~~~~~~~~~^^ File "/usr/lib/python3.13/site-packages/pyrpkg/cli.py", line 2878, in patch self.cmd.patch(self.args.suffix, rediff=self.args.rediff) ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.13/site-packages/pyrpkg/__init__.py", line 2208, in patch open(os.path.join(self.path, outfile), 'w').write(output) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^ TypeError: write() argument must be str, not bytes
The output returned from the subprocess.Popen() call that runs the patch utility is a bytes object, not a str, so the output file has to be opened 'wb' to write output into it. This change fixes writing the patch file, but not the previous extracted-sources-path issue:
output
subprocess.Popen()
patch
str
'wb'
--- /tmp/pyrpkg_init.orig.py 2025-04-02 03:19:24.828275435 -0400 +++ /tmp/pyrpkg_init.py 2025-04-02 03:22:44.750433198 -0400 @@ -2205,7 +2205,8 @@ output = ''.join(newhead) + output # Write out the patch - open(os.path.join(self.path, outfile), 'w').write(output) + with open(os.path.join(self.path, outfile), 'wb') as patchout: + patchout.write(output) # Add it to the index # Again this returns a blank line we want to keep quiet