I have a simple script that applies a patch to a given package, and, since each time said package is upgraded the patch gets overridden, I would really like to automatically apply the patch after every upgrade.
To accomplish this, I created a file in /etc/apt/apt.conf.d/
and added a hook for DPkg::Post-Invoke
. As documented by man apt-get
, this hook is run by apt-get
after installing a package with dpkg
. However this hook does not seem to have any information whatsoever about which particular package has been installed, so I cannot know if I have to apply the patch or not. Nothing gets passed to its stdin, nothing gets passed as argument, and the man page says nothing about it.
So to solve this I did the only thing that I could think of: I added another hook for DPkg::Pre-Install-Pkgs
, which gets run by apt-get
before packages are installed. This hook gets (through stdin) the list of .deb
files which are going to be installd by dpkg
, so I just check whether any file name matches the name of the package I want to patch, and if so I create a file in /tmp
. When my other hook is executed, it first checks for the existence of said file and, if present, applies the patch to the package that has just been installed.
Here's the file I've created in /etc/apt/apt.conf.d/
:
DPkg::Pre-Install-Pkgs {
"while read -r pkg; do case $pkg in *somepkg*) touch /tmp/.patch && exit 0; esac done < /dev/stdin";
};
DPkg::Post-Invoke {
"[ -f /tmp/.patch ] && /home/marco/scripts/apply_somepkg_patch.sh && rm -f /tmp/.patch; exit 0";
};
To be clear: the apply_somepkg_patch.sh
simply edits the contents of a file provided by the package. I want said file to be upgraded and patched each time, I don't want to "lock" it so it doesn't get upgraded.
Now, while this all works just fine, it looks really dirty and somehow wrong to me. Is there any cleaner way to accomplish this? Perhaps only using the DPkg::Post-Invoke
hook? Or, in other words, is there a way to know which package got installed in the DPkg::Post-Invoke
hook?
EDIT: adding a detailed example of what I'm doing just to be 101% clear, even though I don't think it adds any more information to what I said above.
Suppose somepkg
is the package I'm talking about, and somefile
is the file installed by such package which I want to patch.
-
First installation of
somepkg
, content ofsomefile
:some_opt1 = some_value some_opt2 = some_value some_opt3 = a, b, c, d some_opt4 = some_value
-
Apply patch, changing it to:
some_opt1 = some_value some_opt2 = some_value some_opt3 = X, Y, Z, d some_opt4 = some_value
-
Upgrade of
somepkg
, contentssomefile
after upgrade:some_opt1 = some_value some_opt2 = some_value some_opt5 = some_value some_opt3 = a, b, c, d some_opt6 = some_value some_opt4 = some_value
-
Apply patch, changing it to:
some_opt1 = some_value some_opt2 = some_value some_opt5 = some_value some_opt3 = X, Y, Z, d some_opt6 = some_value some_opt4 = some_value
Now, what's the somepackage
, where somefile
is, what's inside somefile
: this is all completely irrelevant for my question. All you need to know is that I want to dynamically modify the contents of somefile
, which is part of somepkg
, after getting the upgraded version of the file.
This obviously cannot be done statically: I need a script to read somefile
, parse its content and patch it accordingly. Therefore, if I want my script to be automatically ran each time somepkg
gets updated, I need to make apt-get
run it automatically for me.
Best Answer
There’s no nice way to do this with
apt
ordpkg
hooks of the style you’re currently using. There might be a simple way of handling such patches on upgrades for the specific package and file you’re modifying, but if you want a generic solution, I think the best approach in Debian currently is to use file triggers.This involves creating a (simple) package which will take care of patching the file on upgrades of the other package (the one containing the file you wish to patch). Your patching package needs to declare its interest in a file trigger; to do so, add a file named
debian/triggers
) containing the single lineThen in the package’s
postinst
(debian/postinst
), check if the first argument istriggered
, and if it is, run your patching script (or merge that in yourpostinst
). If you want to keep your patching script separate, you could ship it in your patching package to keep things contained.Once all that’s done, build and install your patching package, and then whenever you upgrade the package you’re modifying, your patching package’s
postinst
will be called.