Our team frequently performs customization to various packages distributed with RHEL/CentOS. Our workflow involves installing the SRPM, executing rpmbuild -bp
to unpack and patch the source, making our changes and creating a .patch to be included in the specfile, and building the new customized SRPM for later use with mock:
$ rpm -i grub-0.97-13.5.1.src.rpm
$ rpmbuild -bp rpmbuild/SPECS/grub.spec
$ cp -a rpmbuild/BUILD/grub-0.97 grub-0.97.orig
$ cd rpmbuild/BUILD/grub-0.97
# Make modifications, generate .patch against ".orig" copy
$ vim rpmbuild/SPECS/grub.spec
# Add custom .patch to specfile, update version, etc
$ rpmbuild -bs rpmbuild/SPECS/grub.spec
$ mock -r default-x86_64.cfg rpmbuild/SRPMS/grub-0.97-13.5.1.custom-1.src.rpm
This process works well but we are not currently using any form of source control to keep track of our modifications and specfile changes. Based on my (admittedly basic) understanding of git, I think it should be possible to inject it into this workflow and leverage some of its power to optimize a few of the steps (in addition to the normal benefits of SCM).
For example, rather than creating a copy of the source to diff
against later we could create an initial commit of the upstream patched source and then make our modifications. When ready, use git format-patch
to create our feature patch and add it to the specfile.
I would also like to version control the specfiles as well, though I'm not sure how best to achieve that.
So my question is threefold:
Extra credit: Assuming a git-based workflow, how would I structure a central repository to accept pushes? One repo with submodules? One repo per package?
Does anyone out there use SCM when customizing upstream packages?
Sure. This is pretty common.
What is the most effective way to integrate git into our workflow? Is there a better workflow that is more conducive to version-controlled custom RPM authoring?
I don't know about most effective, but here's what I do. I start with
the following ~/.rpmmacros
file:
%_topdir %(echo ${RPM_TOPDIR:-$HOME/redhat})
%_specdir %{_topdir}/PACKAGES/%{name}/%{version}
%_sourcedir %{_topdir}/PACKAGES/%{name}/%{version}/sources
%_rpmdir %{_topdir}/PACKAGES/%{name}/%{version}/rpms
If I install a package (say, foo-1.0-1.src.rpm), the spec file ends up in
~/redhat/PACKAGES/foo/1.0/foo.spec
, and the source tarball (and any
patches) end up in ~/redhat/PACKAGES/foo/1.0/sources
.
Now I initialize the package directory as a git repository:
cd ~/redhat/PACKAGES/foo/1.0
git init
git add foo.spec sources/*.patch
git ci -m 'initial commit'
There's nothing special about recording changes to the spec file:
git ci -m 'made some really spiffy changes' foo.spec
If I need to make changes to package source files, I do this:
rpmbuild -bp foo.spec
And now I create a temporary git repository:
cd ~/redhat/BUILD/foo-1.0
git init
git add .
git ci -m 'initial commit'
git tag upstream
From this point on, if I make any changes I can generate patches against the upstream package like this:
git diff upstream
Or if I've made a series of commits, I can use git's format-patch
command
to create a series of patches:
$ git format-patch upstream
0001-added-text.patch
0002-very-important-fix.patch
And these can be copied into the appropriate sources
directory and added
to the spec file.
Note that the temporary git repository I've created for tracking changes in
the build directory will be obliterated next time I run rpmbuild
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With