Bug 239745 - symlink from /etc/alternatives/emacs to /usr/bin/emacs is not created
symlink from /etc/alternatives/emacs to /usr/bin/emacs is not created
Status: CLOSED ERRATA
Product: Fedora
Classification: Fedora
Component: emacs (Show other bugs)
rawhide
All Linux
medium Severity medium
: ---
: ---
Assigned To: Chip Coldwell
:
Depends On:
Blocks:
  Show dependency treegraph
 
Reported: 2007-05-10 17:54 EDT by Matěj Cepl
Modified: 2014-12-10 23:46 EST (History)
3 users (show)

See Also:
Fixed In Version: 22.1-1.fc7
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Environment:
Last Closed: 2007-07-11 17:38:09 EDT
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:


Attachments (Terms of Use)
spec patch to implement %ghost /usr/bin/emacs and scriptlet conditionals (2.37 KB, patch)
2007-05-22 18:29 EDT, Charles R. Anderson
no flags Details | Diff

  None (edit)
Description Matěj Cepl 2007-05-10 17:54:29 EDT
Description of problem:
When upgrading emacs (from your repository) I didn't have /usr/bin/emacs command
suddenly.

Version-Release number of selected component (if applicable):
emacs-22.0.99-1.fc6

How reproducible:
100%

Steps to Reproduce:
1.upgrade emacs

  
Actual results:
There isn't /usr/bin/emacs available

Expected results:
It should be
Comment 1 Charles R. Anderson 2007-05-15 17:50:43 EDT
I confirm the same problem here.

Upgraded from 22.0.99-1.fc7 to:

emacs-22.0.99-2.fc7
emacs-common-22.0.99-2.fc7

I had an emacs symlink before, none now.  Alternatives link is there pointing to
versioned binary:

ls -l /etc/alternatives/emacs
lrwxrwxrwx 1 root root 22 2007-05-15 17:46 /etc/alternatives/emacs ->
/usr/bin/emacs-22.0.99*

Comment 2 Charles R. Anderson 2007-05-15 18:02:03 EDT
Shouldn't these scriptlets be wrapped in conditionals like I see in other
packages that use alternatives?  I think the preuninstall for 22.0.99-1.fc7 is
getting called after the postinstall for 22.0.99-2.fc7, causing the link to be
removed right after it is added.

> rpm -q --scripts emacs
postinstall scriptlet (using /bin/sh):
alternatives --install /usr/bin/emacs emacs /usr/bin/emacs-22.0.99 80

preuninstall scriptlet (using /bin/sh):
alternatives --remove emacs /usr/bin/emacs-22.0.99

E.g. sendmail (trimmed to only the bits that handle alternatives):

postinstall scriptlet (using /bin/sh):
# Set up the alternatives files for MTAs.
/usr/sbin/alternatives --install /usr/sbin/sendmail mta
/usr/sbin/sendmail.sendmail 90 \
        --slave /usr/bin/mailq mta-mailq /usr/bin/mailq.sendmail \
        --slave /usr/bin/newaliases mta-newaliases /usr/bin/newaliases.sendmail \
        --slave /usr/bin/rmail mta-rmail /usr/bin/rmail.sendmail \
        --slave /usr/lib/sendmail mta-sendmail /usr/lib/sendmail.sendmail \
        --slave /etc/pam.d/smtp mta-pam /etc/pam.d/smtp.sendmail \
        --slave /usr/share/man/man8/sendmail.8.gz mta-sendmailman
/usr/share/man/man8/sendmail.sendmail.8.gz \
        --slave /usr/share/man/man1/mailq.1.gz mta-mailqman
/usr/share/man/man1/mailq.sendmail.1.gz \
        --slave /usr/share/man/man1/newaliases.1.gz mta-newaliasesman
/usr/share/man/man1/newaliases.sendmail.1.gz \
        --slave /usr/share/man/man5/aliases.5.gz mta-aliasesman
/usr/share/man/man5/aliases.sendmail.5.gz \
        --initscript sendmail
exit 0

preuninstall scriptlet (using /bin/sh):
if [ $1 = 0 ]; then
        /usr/sbin/alternatives --remove mta /usr/sbin/sendmail.sendmail
fi
exit 0

postuninstall scriptlet (using /bin/sh):
if [ "$1" -ge "1" ]; then
        mta=`readlink /etc/alternatives/mta`
        if [ "$mta" == "/usr/sbin/sendmail.sendmail" ]; then
                /usr/sbin/alternatives --set mta /usr/sbin/sendmail.sendmail
        fi
fi
exit 0
Comment 3 Chip Coldwell 2007-05-16 15:43:53 EDT
(In reply to comment #2)
> Shouldn't these scriptlets be wrapped in conditionals like I see in other
> packages that use alternatives?  I think the preuninstall for 22.0.99-1.fc7 is
> getting called after the postinstall for 22.0.99-2.fc7, causing the link to be
> removed right after it is added.
> 
> > rpm -q --scripts emacs
> postinstall scriptlet (using /bin/sh):
> alternatives --install /usr/bin/emacs emacs /usr/bin/emacs-22.0.99 80

What happens if you run that command manually?

Chip
Comment 4 Charles R. Anderson 2007-05-16 15:57:27 EDT
I get a /usr/bin/emacs symlink if I run that command manually.
Comment 5 Jeremy Katz 2007-05-22 08:41:14 EDT
The packages in F7 as it stands don't have the alternatives stuff and that
wouldn't really be appropriate to add at this late stage of the game, so
dropping from F7Blocker as it's not going to block things
Comment 6 Chip Coldwell 2007-05-22 09:24:54 EDT
I believe I have this fixed in the current devel/ branch.  I'm just waiting for
Jakub's new glibc to hit the buildroots before I do a new build.

Chip
Comment 7 Chip Coldwell 2007-05-22 15:12:56 EDT
The issue here is arguably a bug in alternatives.  Here's what happens:

The old emacs package installs a symlink in /usr/bin

emacs -> emacs-22.0.95

Then you upgrade the package to emacs-22.0.990.  The scriptlets are run in this
order:

%pre of new package
(package install)
%post of new package
%preun of old package
(removal of old package)
%postun of old package

The %post of emacs-22.0.990 runs while the /usr/bin/emacs symlink still exists,
and in that case, alternatives fails to install its own symlink but nonetheless
returns success!  Then removal of the old package removes the symlink in
/usr/bin/emacs.  I would argue that in this case, alternatives should fail and
therefore the scriptlet would fail also, giving the user a clue that something
has gone awry.

Fundamentally, the issue here is that we are switching from having a symlink
that is not managed by alternatives to having a symlink in the identical
location that is.  IOW, future upgrades of emacs beyond 22.0.990-1 should
maintain this symlink correctly, but the upgrade path from 22.0.95-X to
22.0.990-1 is fraught with danger.

The process works just fine if instead of upgrading emacs, you simply remove the
old package first:

# rpm -e emacs emacs-common

then install

# yum install -y emacs

and you will have the symlink as expected.

Because of the ordering of the scriptlets (new package scriptlets run before old
package scriptlets), it's hard to get this upgrade right.  I'm inclined to close
this bug as WONTFIX and just post the instructions above as a workaround.

Chip
Comment 8 Charles R. Anderson 2007-05-22 15:38:33 EDT
I disagree that this should be closed as WONTFIX.  You shouldn't create pain in
the form of manual upgrade instructions if there is a way to work around the
issue in an automated manner.

You shouldn't be removing the symlink in %preun unless this is the last instance
of the package being removed.  i.e. during package upgrades, %preun shouldn't be
calling alternatives --remove.  The correct way to fix this is to use the same
method that sendmail uses as I quoted above in comment #2:

%preun
if [ $1 = 0 ]; then
        alternatives --remove emacs /usr/bin/emacs-22.0.99
fi
exit 0

The conditional says that if there will be zero instances of this package
installed after the uninstall is completed, then run the alternatives command. 
The condition is only true for removal of the final copy of emacs, not during
upgrades where there will be the new upgraded emacs installed after the
completed transaction.

There is no conditional on the %post script, since there is no harm in running
the alternatives --install multiple times, and this will be necessary to make
sure the symlink gets installed even during upgrades where there might not have
been one previously.

However, if you have a symlink already in place that wasn't installed by
alternatives before, it must be deleted first, as I discovered in this test:

I tested as follows.  First I created a symlink like so:

#ln -snf /usr/bin/emacs-22.0.99 /usr/bin/emacs
#ls -l /usr/bin/emacs
lrwxrwxrwx 1 root root 22 2007-05-22 15:34 /usr/bin/emacs -> /usr/bin/emacs-22.0.99*

Then I reran the alternatives command:

#alternatives --install /usr/bin/emacs emacs /usr/bin/emacs-22.0.99 80

But it didn't overwrite the existing symlink:

#ls -l /usr/bin/emacs
lrwxrwxrwx 1 root root 22 2007-05-22 15:34 /usr/bin/emacs -> 
/usr/bin/emacs-22.0.99*

After deleting the symlink the alternatives command works:

#rm -f /usr/bin/emacs
#alternatives --install /usr/bin/emacs emacs /usr/bin/emacs-22.0.99 80
#ls -l /usr/bin/emacs
lrwxrwxrwx 1 root root 22 2007-05-22 15:34 /usr/bin/emacs -> /usr/bin/emacs-22.0.99*

So %post should end up looking something like this (we don't want the rm -f to
fail and exit the rpm upgrade process, hence the "|| :")

%post
rm -f /usr/bin/emacs || :
alternatives --install /usr/bin/emacs emacs /usr/bin/emacs-22.0.99 80
exit 0

Actually, there may be other issues here since the actual binary name is
versioned.  I'm not aware of any precedent for versioned real binaries being
used with alternatives.  It might be safer to use the method used by sendmail,
calling the real binary after the type of alternative installed:

/usr/bin/emacs.emacs
/usr/bin/emacs.xemacs

etc.
Comment 9 Chip Coldwell 2007-05-22 15:49:09 EDT
(In reply to comment #8)

> So %post should end up looking something like this (we don't want the rm -f to
> fail and exit the rpm upgrade process, hence the "|| :")
> 
> %post
> rm -f /usr/bin/emacs || :
> alternatives --install /usr/bin/emacs emacs /usr/bin/emacs-22.0.99 80
> exit 0

Wrong!  The %post of the new package above runs *before* the removal of the old
package, which gleefully removes the symlink you just installed.

The problem is that we have to change the scriptlets in the old packages to make
this work smoothly -- and we can't because they are already out there!

Chip
Comment 10 Chip Coldwell 2007-05-22 15:52:15 EDT
The only hope would be to put something into %posttrans of the new package that
would check to see if the symlink had disappeared and replace it if so.
Comment 11 Charles R. Anderson 2007-05-22 15:57:03 EDT
I was under the impression that this package was going into F7, but it appears
that is not so.  If this problem has only existed in rawhide, and not a released
Fedora, then I would be fine with a manual workaround.  The %post above would
still be necessary for the future packages, though, to guarantee that the
symlink got updated properly on future upgrades.
Comment 12 Charles R. Anderson 2007-05-22 16:14:35 EDT
The current emacs-22.0.95-1.fc7 in rawhide doesn't have any scripts:

# rpm -q --scripts emacs

So the problem in comment #9 won't exist for released versions of Fedora, which
don't have alternatives for /usr/bin/emacs.
Comment 13 Chip Coldwell 2007-05-22 16:20:07 EDT
(In reply to comment #12)
> The current emacs-22.0.95-1.fc7 in rawhide doesn't have any scripts:
> 
> # rpm -q --scripts emacs
> 
> So the problem in comment #9 won't exist for released versions of Fedora, which
> don't have alternatives for /usr/bin/emacs.

Wrong!  

$ rpm -qlp emacs-22.0.95-1.fc7.x86_64.rpm 
/usr/bin/emacs
/usr/bin/emacs-22.0.95
/usr/bin/emacs-22.0.95-x
/usr/bin/emacs-x
/usr/libexec/emacs
/usr/libexec/emacs/22.0.95
/usr/libexec/emacs/22.0.95/x86_64-redhat-linux-gnu
/usr/share/applications/gnu-emacs.desktop
/usr/share/pixmaps/emacs.png

The old package claims to own the symlink, whereas the new package does not
(it's a side effect of running alternatives in the %post script).  Therefore,
after an upgrade, the symlink will be removed.

Chip

Comment 14 Charles R. Anderson 2007-05-22 16:25:53 EDT
Ok, I concede on that point then.  I see no easy way to fix this.  There may be
a hard way to fix this, in which case I think emacs should not use alternatives
this late in the F7 cycle.  If emacs 22.0.99 will be in F7, it is my opinion
that the alternatives changes should be reverted.

Comment 15 Charles R. Anderson 2007-05-22 16:56:37 EDT
What if /usr/bin/emacs is owned by the new package as a %ghost file?

%files
...
%ghost /usr/bin/emacs

will that prevent the removal problem since the new package will now own the
symlink like the old package did?
Comment 16 Charles R. Anderson 2007-05-22 18:29:06 EDT
Created attachment 155208 [details]
spec patch to implement %ghost /usr/bin/emacs and scriptlet conditionals

I built emacs-22.0.99-2 with this patch and tested the upgrade from
emacs-22.0.95 (pre-alternatives).  The %ghost appears to fix the issue--the
/usr/bin/emacs symlink gets created properly by alternatives and is no longer
erased by rpm during the upgrade transaction.  I tested both emacs and
emacs-nox and also manually changing the alternatives between them.  All
appears to work fine.
Comment 17 Chip Coldwell 2007-05-23 09:36:15 EDT
(In reply to comment #16)
> Created an attachment (id=155208) [edit]
> spec patch to implement %ghost /usr/bin/emacs and scriptlet conditionals

Looks good; I'll include that in F-8.  It looks like F-7 is going to revert to
the pre-alternatives method for GA.

Thanks-a-million

Chip
Comment 18 Fedora Update System 2007-06-26 23:50:25 EDT
emacs-22.1-1.fc7 has been pushed to the Fedora 7 testing repository.  If problems still persist, please make note of it in this bug report.
Comment 19 Michal Jaegermann 2007-07-04 16:10:41 EDT
The problem definitely persists with emacs-22.1-1.fc8 from rawhide.
'rpm -q --scripts emacs' prints only this:

preuninstall scriptlet (using /bin/sh):
if [ $1 -eq 0 ] ; then
  alternatives --remove emacs /usr/bin/emacs-22.1
fi

and sure enough /usr/bin/emacs does not exist unless created manually;
say with

alternatives --install /usr/bin/emacs emacs /usr/bin/emacs-22.1 80

(Not mentioning that I cannot kill that seriously broken colour on
a backgroud when running with -nw.  An old trick 'emacs -nw -bg none'
does not work anymore.  Well, not entirely true.  I can run
'emacs -nw --color=no' but that is somewhat overdoing things.)
Comment 20 Chip Coldwell 2007-07-05 09:42:44 EDT
(In reply to comment #19)
> The problem definitely persists with emacs-22.1-1.fc8 from rawhide.
> 'rpm -q --scripts emacs' prints only this:
> 
> preuninstall scriptlet (using /bin/sh):
> if [ $1 -eq 0 ] ; then
>   alternatives --remove emacs /usr/bin/emacs-22.1
> fi

File a bug against rpm, then, because it is not reporting the %posttrans
scriptlet that does the alternatives install.

> and sure enough /usr/bin/emacs does not exist unless created manually;

Remove the old package, then do a fresh install of the new one and report the
results here, please.

Chip
Comment 21 Charles R. Anderson 2007-07-09 15:59:13 EDT
We had this solved with the %ghost /usr/bin/emacs.  Why did you decide to change
to %posttrans?
Comment 22 Fedora Update System 2007-07-11 17:37:58 EDT
emacs-22.1-1.fc7 has been pushed to the Fedora 7 stable repository.  If problems still persist, please make note of it in this bug report.
Comment 23 Ville Skyttä 2007-08-30 02:42:24 EDT
FWIW, xemacs had the same problem back when I switched it to use alternatives,
IMO it is indeed a bug in alternatives (#104940) and only in the Red Hat/Fedora
one (IIRC it doesn't exist in the original implementation in Debian).
Comment 24 Charles R. Anderson 2007-08-30 08:51:17 EDT
The fix in Comment #22 works for me.  The reason it didn't work initially, is
because of the existing testing package I had installed.  Starting from the last
official release of emacs and upgrading to 22.1-1.fc7 works properly with the
symlink.
Comment 25 Robin Green 2011-04-22 10:26:57 EDT
I am seeing this again after a preupgrade from Fedora 14 to 15.
Comment 26 Jens Petersen 2014-12-10 23:46:51 EST
Revisiting this in the context of another package, it seems to me
that a newly %ghost'ed file keeps the original file on disk which
prevents alternatives from creating the new symlink.

Adding %pre logic to remove any existing file seems to be
a workaround, but I agree that alternatives/rpm could
handle this better.

Note You need to log in before you can comment on or make changes to this bug.