Differences between revisions 1 and 19 (spanning 18 versions)
Revision 1 as of 2006-06-03 15:50:07
Size: 1878
Editor: ?Andreas Fester
Comment:
Revision 19 as of 2010-04-18 05:40:37
Size: 5252
Editor: ?JonathanNieder
Comment: oops, extra paren
Deletions are marked like this. Additions are marked like this.
Line 2: Line 2:
Sometimes, it is necessary for a package to get a new name. Although this should rather seldom be the case, there are some situations when it makes sense, for example when the name of the upstream application changes. Of course an ''apt-get dist-upgrade'' should still seamlessly upgrade the package, best by completely removing the old package and installing the new one as a replacement.
Line 3: Line 4:
Sometimes, it is necessary for a package to get a new name. Although it should rather seldom be the case, there are some situations when this makes sense, for example when the name of the upstream application changes. Of course an ''apt-get dist-upgrade'' should seamless upgrade the package, best by completely removing the old package and installing the new one as a replacement.
Basically, the solution is to define a binary dummy package with the same name as the old package in the control file of the new package. The new source package takes over the binary dummy package, and the old source package, which is then binaryless, will be cleaned up by {{{rene}}}, an archive cleanup tool.
Line 7: Line 7:
Assume that the last upstream version of the old package "oldPkg" was 1.5 and the package was renamed to "newPkg" for version 2.0.

Then, the dummy package is defined like this in debian/control:
Line 8: Line 12:
 Package: oldpkg
 Depends: newpkg
 Version: 1.0
 Package: oldPkg
 Depends: newPkg
 Architecture: all
Line 13: Line 17:
This entry defines the binary dummy package. It will get version 2.0-1 and automatically be pulled in by an {{{apt-get dist-upgrade}}} if an earlier version of oldPkg was already installed.

The package only installs the mandatory files in /usr/share/doc/oldPkg.

Since it depends on newPkg, it also installs the new package.

Note that the package does not contain any architecture specific files anymore and therefore the Architecture is set to "All", even if it was "Any" before.

The new package is defined like this:
Line 14: Line 28:
 Package: newpkg
 Replaces: oldpkg (<< 1.0)
 Package: newPkg
 Provides: oldP
kg
 Replaces: oldPkg (<< 2.0-1)
 Conflicts: oldPkg (<< 2.0-1)
Line 17: Line 33:
The {{{Provides:}}} entry makes sure that reverse dependencies do net get broken so that other packages which depend on the old unversioned package name can still be installed.
Line 18: Line 35:
== Method B == Please make sure not to forget the Debian-revision of the first renamed version which entered/will enter the archive in the Replaces: and Conflicts: line unless you want to stumble across bugs like [[DebianBug:397993|#397993]].
Line 20: Line 37:
There is an even more elegant way which installs less files and effectively provides a real replacement mechanism. == Method B (NOT CURRENTLY APPLICABLE) ==
There is an even more elegant way which installs fewer files and would effectively provide a real replacement mechanism if it worked.
Line 25: Line 43:
 Package: oldpkg
 Depends: newpkg
 Section: transitional
 Package: oldPkg
 Depends: newPkg
 Architecture: all
 Description: transitional dummy package
Line 28: Line 49:

The dummy package only installs a link (and nothing else!) like {{{/usr/share/doc/oldpkg -> /usr/share/doc/newpkg}}}, for example with the dh_link debhelper script.
The dummy package only installs a link (and nothing else!) like {{{/usr/share/doc/oldPkg -> /usr/share/doc/newPkg}}}, for example with the dh_link debhelper script.
Since {{{dpkg}}} ignores the directory/link distinction, to get an actual link you would need a snippet like the following in postinst.
{{{
 test -L /usr/share/doc/oldPkg || rmdir /usr/share/doc/oldPkg || :
 test -e /usr/share/doc/oldPkg || ln -sT newPkg /usr/share/doc/oldPkg || :
}}}
Line 34: Line 59:
 Package: newpkg
 Replaces: oldpkg
 Provides: oldpkg
 Package: newPkg
 Provides: oldP
kg
 Replaces: oldPkg
 Conflicts: oldPkg (<< 2.0)
Line 39: Line 65:
The new package installs all its necessary files and the same link as the dummy package, {{{/usr/share/doc/oldpkg -> /usr/share/doc/newpkg}}} The new package installs all its necessary files, '''and the same link as the dummy package''', {{{/usr/share/doc/oldPkg -> /usr/share/doc/newPkg}}}.
Line 41: Line 67:
Now, when an earlier version of the oldPkg is installed and the system is upgraded with {{apt-get dist-upgrade}}, the new version of the dummy package is installed which pulls in the new package newPkg. The link is then taken over by newPkg, so that no installed files remain for the old dummy package oldPkg. {{{dpkg}}} is aware of this situation and notices that oldPkg is now completely replaced. However, through a bug in dpkg, it tries to configure the old dummy package at a later time, which fails because the package was already removed. Thus, at least for etch, this approach can not be used. Now, when an earlier version of the oldPkg is installed and the system is upgraded with {{{apt-get dist-upgrade}}}, the new version of the dummy package is installed which pulls in the new package newPkg. The link is then taken over by newPkg, so that no installed files remain for the old dummy package oldPkg. {{{dpkg}}} is aware of this situation and notices that oldPkg is now completely replaced.

Problems:

 * APT tries to configure the old dummy package at a later time, which fails because the package was already removed. See [[http://lists.debian.org/deity/2006/06/msg00012.html|the relevant thread from the deity mailing list]].
 * The new package (since installed through a dependency) is marked as automatically installed. Once oldPkg disappears, there is no obvious reason to keep newPkg any more, so it is removed on the next autoremove run. Fixing this would be good for Method A, too.
 Fix: teach the package manager that oldPkg was a transitional package so its dependencies can inherit its automatically installed status. This seems to require a change in policy (for example, a new {{{transitional}}} section). See [[DebianBug:574851|Bug #574851]].
 * During the transition, oldPkg might be needed to satisfy versioned dependencies on the old package name. If oldPkg and the packages depending on it are already installed, this will work fine ({{{dpkg}}} has support for this case), but installing oldPkg and a package with a versioned dependency on it in separate {{{dpkg}}} runs will not work: after oldPkg is installed, it disappears before {{{dpkg}}} gets a chance to know about the package that would depend on it.
 Workaround 1: if it needs to be kept around, install oldPkg at the same run as or later than at least one package depending on it. No higher-level package manager in Debian seems to do this.
 Workaround 2: do not add the /usr/share/doc/oldPkg link to newPkg until all versioned dependencies on oldPkg have been eliminated.
----
 . CategoryDeveloper

Why?

Sometimes, it is necessary for a package to get a new name. Although this should rather seldom be the case, there are some situations when it makes sense, for example when the name of the upstream application changes. Of course an apt-get dist-upgrade should still seamlessly upgrade the package, best by completely removing the old package and installing the new one as a replacement.

Basically, the solution is to define a binary dummy package with the same name as the old package in the control file of the new package. The new source package takes over the binary dummy package, and the old source package, which is then binaryless, will be cleaned up by rene, an archive cleanup tool.

Method A

Assume that the last upstream version of the old package "oldPkg" was 1.5 and the package was renamed to "newPkg" for version 2.0.

Then, the dummy package is defined like this in debian/control:

 Package: oldPkg
 Depends: newPkg
 Architecture: all
 Description: transitional dummy package

This entry defines the binary dummy package. It will get version 2.0-1 and automatically be pulled in by an apt-get dist-upgrade if an earlier version of oldPkg was already installed.

The package only installs the mandatory files in /usr/share/doc/oldPkg.

Since it depends on newPkg, it also installs the new package.

Note that the package does not contain any architecture specific files anymore and therefore the Architecture is set to "All", even if it was "Any" before.

The new package is defined like this:

 Package: newPkg
 Provides: oldPkg
 Replaces: oldPkg (<< 2.0-1)
 Conflicts: oldPkg (<< 2.0-1)

The Provides: entry makes sure that reverse dependencies do net get broken so that other packages which depend on the old unversioned package name can still be installed.

Please make sure not to forget the Debian-revision of the first renamed version which entered/will enter the archive in the Replaces: and Conflicts: line unless you want to stumble across bugs like #397993.

Method B (NOT CURRENTLY APPLICABLE)

There is an even more elegant way which installs fewer files and would effectively provide a real replacement mechanism if it worked.

The dummy package is defined like this in debian/control:

 Section: transitional
 Package: oldPkg
 Depends: newPkg
 Architecture: all
 Description: transitional dummy package

The dummy package only installs a link (and nothing else!) like /usr/share/doc/oldPkg -> /usr/share/doc/newPkg, for example with the dh_link debhelper script. Since dpkg ignores the directory/link distinction, to get an actual link you would need a snippet like the following in postinst.

 test -L /usr/share/doc/oldPkg || rmdir /usr/share/doc/oldPkg || :
 test -e /usr/share/doc/oldPkg || ln -sT newPkg /usr/share/doc/oldPkg || :

The new package is defined like this in debian/control:

 Package: newPkg
 Provides: oldPkg
 Replaces: oldPkg
 Conflicts: oldPkg (<< 2.0)

The new package installs all its necessary files, and the same link as the dummy package, /usr/share/doc/oldPkg -> /usr/share/doc/newPkg.

Now, when an earlier version of the oldPkg is installed and the system is upgraded with apt-get dist-upgrade, the new version of the dummy package is installed which pulls in the new package newPkg. The link is then taken over by newPkg, so that no installed files remain for the old dummy package oldPkg. dpkg is aware of this situation and notices that oldPkg is now completely replaced.

Problems:

  • APT tries to configure the old dummy package at a later time, which fails because the package was already removed. See the relevant thread from the deity mailing list.

  • The new package (since installed through a dependency) is marked as automatically installed. Once oldPkg disappears, there is no obvious reason to keep newPkg any more, so it is removed on the next autoremove run. Fixing this would be good for Method A, too.

    Fix: teach the package manager that oldPkg was a transitional package so its dependencies can inherit its automatically installed status. This seems to require a change in policy (for example, a new transitional section). See Bug #574851.

  • During the transition, oldPkg might be needed to satisfy versioned dependencies on the old package name. If oldPkg and the packages depending on it are already installed, this will work fine (dpkg has support for this case), but installing oldPkg and a package with a versioned dependency on it in separate dpkg runs will not work: after oldPkg is installed, it disappears before dpkg gets a chance to know about the package that would depend on it. Workaround 1: if it needs to be kept around, install oldPkg at the same run as or later than at least one package depending on it. No higher-level package manager in Debian seems to do this. Workaround 2: do not add the /usr/share/doc/oldPkg link to newPkg until all versioned dependencies on oldPkg have been eliminated.