Pacman

Historical bug tracker for the Pacman package manager.

The pacman bug tracker has moved to gitlab:
https://gitlab.archlinux.org/pacman/pacman/-/issues

This tracker remains open for interaction with historical bugs during the transition period. Any new bugs reports will be closed without further action.
Tasklist

FS#45988 - pacman upgrade runs wrong pre_upgrade

Attached to Project: Pacman
Opened by Chris Severance (severach) - Friday, 14 August 2015, 23:35 GMT
Last edited by Allan McRae (Allan) - Monday, 14 December 2015, 14:14 GMT
Task Type Bug Report
Category General
Status Closed
Assigned To No-one
Architecture All
Severity Low
Priority Normal
Reported Version 4.2.1
Due in Version Undecided
Due Date Undecided
Percent Complete 100%
Votes 0
Private No

Details

Summary and Info:

When pacman upgrades a package it should run pre_upgrade from the package version that is leaving and run post_upgrade from the package version that is arriving. Unfortunately it runs pre_upgrade from the new version.

Steps to Reproduce:

See enclosed PKGBUILD.
   PKGBUILD (0.8 KiB)
This task depends upon

Closed by  Allan McRae (Allan)
Monday, 14 December 2015, 14:14 GMT
Reason for closing:  Not a bug
Additional comments about closing:  Working as documented
Comment by Allan McRae (Allan) - Saturday, 15 August 2015, 02:15 GMT
This is expected. Otherwise you need to be psychic to know that your pre_upgrade() in the installed package does everything you want before installing the updated package.
Comment by Chris Severance (severach) - Saturday, 15 August 2015, 03:04 GMT
In all cases pre_upgrade must include extra code to cover past mistakes. The problem with running the wrong version is that that pre_upgrade must also include extra code to cover every possible change from any version to any other version. This mistake turns a linear problem into a factorial problem.

If the right version of pre_upgrade was run, it would do what is appropriate for the old environment in preparation for the update and its new environment. Only mistakes would need extra code.

My guess for always running the new install is that its the one you have. The old install may not be readily available.
Comment by Andrew Gregory (andrewgregory) - Saturday, 15 August 2015, 03:39 GMT
If the upgraded version of the package has new pre-installation requirements, the old package's pre_upgrade hook can't possibly handle them. The new package's pre_upgrade can, however, handle any cleanup required by the old package. For example, I hope to improve pacman's handling of dynamically created users in the near future. This will very likely require that users are created in pre_install/pre_upgrade rather than post_install/post_upgrade. If a new version of the package requires a new user that the previous version did not, the old package's pre_upgrade script obviously will not add the required user, resulting in a broken install.

Can you give a concrete example of a situation that would benefit from your proposed change?
Comment by Chris Severance (severach) - Saturday, 15 August 2015, 09:16 GMT
In AUR basis-pro5 I 'chattr +i' some files so root can't edit them. In pre_remove and pre_upgrade they must be chattr +i so pacman can delete them.

Then I decided to change the folder from /usr/local to /usr/share. Since the new install that is dynamically generated the same way as in the enclosed PKGBUILD only knows about the new folder, the new install chattr -i files that don't yet exist. The old install never runs, the existing files never get chattr -i, and pacman can't delete them. Switch back to the old folder, upgrade, and the files that never got deleted are now in the way. Now both sets of immutable files exist and the upgrade is blocked at every turn. chattr isn't compatible with at least some of fakechroot, tar, and pacman.

Since pacman won't tell me where the files are, the solution is to have the new version panic on failure and chattr -i all possible folders, which can work if the folders are carefully selected by the PKGBUILD maintainer. This can't work with a user selectable folder as I won't search the drive as root for random things to delete. Due to that and other problems, I ended up leaving the working code but not advertising the feature and left the folder /usr/local.

User management is a mess. Unless the user is always there like nobody, I end up chown by name in the installer after adduser has run, not in package() with fakechroot.

The only solution I see to solve both is to split pre_remove into early and late, or old and new. The current pre_remove becomes the new new/late version and a pre_remove_old/early would be added. I can't find any reason why the other install functions would need to be split this way.

Recalling that RPM has 4x2=8 install functions I tried to map them to Arch install functions according to the specs. If I've hit on one of Arch's missing functions, maybe the other is of interest too. Since the reference says so little about the call order I check the table against a working implementation in my AUR AvantFAX.

http://www.rpm.org/max-rpm/s1-rpm-inside-scripts.html
%pre 1 pre_install
%post 1 post_install
%pre 2 pre_upgrade (late)
%post 2 post_upgrade (late)
%preun 0 pre_remove
%postun 0 post_remove
%preun 1 pre_upgrade_early
%postun 1 post_upgrade_early (invalid)

Install call order: pre_install, pacman, post_install
Upgrade call order: pre_upgrade_early, pre_upgrade (late), pacman, (not post_upgrade_early), post_upgrade (late)
Remove call order: pre_remove, pacman, post_remove

Debian has a nice chart: https://wiki.debian.org/MaintainerScripts . Notice that Debian chooses to run pre_upgrade_early and not pre_upgrade (late) which fixes my problem and breaks yours. This is no better or worse than the Arch choice.

In AvantFAX I used 7 RPM install functions, all but the one I deem invalid as I can find no reason to call a post_upgrade_early after a pre_upgrade late has already been called. In AvantFAX "1 pre" moves to post_install which leaves pre_install empty because I thought it better and easier to move the call than to tear apart the improperly designed code. It is likely that "1 preun" could be moved to the new pre_remove_early and the actions of "2 pre" might become less heavy handed.

I see the new pre_remove_early/old as a done deal to stay competitive with RPM. Thanks to a correctly designed install script, adding this function should be easy and trouble free.

Since I'm in this deep I might as well pimp for a purge function like found in Debian that is called on pacman -R --nosave. Notice the post_remove in AvantFAX is a little heavy handed. In other packages I leave the cruft since I have no way to let the user specify. Having both the benefits of Debian and RPM that each other don't have puts Arch in a good position. We would be able to do things like pacman -Rsc --nosave xfce4-panel and have a reasonably clean remove.

The config-files state looks awesome for fully reversible installs where the user forgot to specify --nosave. Do we have that? The charts show how elaborate the Debian packaging system is.

I see a different pacman bug getting in the way of your user creation. It's been a while but I noticed in March 2015 for AvantFAX an upgrade bug when you add a pre/post that wasn't there in the previous version. Maybe it's fixed by now but as I recall, if you add a function, pacman won't run it because it wasn't there in the previous version. As a result I tend to add all 6 pre post functions at least as : to guarantee that pacman won't skip one. Notice that AvantFAX has a dummy function for pre_install, the one function that is almost never used.
Comment by Allan McRae (Allan) - Saturday, 15 August 2015, 10:39 GMT
> In AUR basis-pro5 I 'chattr +i' some files so root can't edit them. In pre_remove and pre_upgrade they must be chattr +i so pacman can delete them.

Well... that is poor packaging.

> Then I decided to change the folder from /usr/local to /usr/share

Your dilemma is easily fixed. In your pre_upgrade function, you can use vercmp to test if the old package version is less than the version that moved files to /usr/share and then chattr the files in /usr/local or /usr/share as appropriate. Search for vercmp in Arch packages to see examples.
Comment by Chris Severance (severach) - Sunday, 16 August 2015, 23:48 GMT
Poor packaging is a given with commercial apps. I'd make that a split package if I could get the AUR to not publish every split name as a separate package. AUR ttf-ms-win8* is a disaster for anything other than boosting package counts. Example: I want win8, win8-indic, and win8-thai. How many PKGBUILD should I download? This works for repositories. It doesn't work for the AUR.

That's as poor of workaround as I've done already. Until we get all the install functions we need, the only current right way is to place a shell script on the system that always matches the version of files on the system. Then running the new pre_upgrade is the best choice since it can run or hack the pre_upgrade early in the shell script then all of the new stuff. AvantFAX was big enough and had good reason to do that. Smaller packages should and could avoid the extra work if pacman wasn't lying. You can't claim it's a pre_upgrade if you're actually running the post-pre_upgrade!
Comment by Allan McRae (Allan) - Monday, 17 August 2015, 00:20 GMT
You have not given one example of what can not be handled by the current upgrade scriptlets. So there is absolutely no justification for the extra complexity you are proposing.

Loading...