Fink:Packaging:Obsolete Packages

From the Fink Wiki
Jump to navigation Jump to search


This page explains a new feature available starting in fink-0.26.0

Over time, packages sometimes get renamed or entirely replaced by other packages. The "obsoletes" mechanism provides a way to deal with the migration to the new package-name for users and package maintainers.

The situation

Package upgrades sometimes involve changes to the package name, but fink does not have a direct way to specify such an upgrade path. For example, when an old foo-ssl/foo pair is replaced by a single foo (or other variant removal situation), a user may have foo-ssl installed. How does the user know that "new version of foo replaces old foo-ssl" without having foo already installed?

A similar problem may occur when shared-library packages contain a -bin or other userland component and the major libversion changes: how do we indicate the upgrade path from foo1-bin to foo2-bin? This could be used in conjunction with migration to -unified packages.

Finally and more generally, a maintainer may decide that a certain package is no longer needed, and its files get redistributed among other packages. How can other packages that need those files and previously depended on the package that formerly contained them be alerted to change to the new dependency?

Note that all these cases involve direct "drop-in" replacements of the old packages. At this time, I do not think "old library versions" are candidates for this system precisely because one cannot assume that simply using a different library-version will always work: by definition, a new library-version means that symbols are likely removed and/or other completely incompatible interface changes have been made. Also, one cannot always change a package's dependency on a lib "in a vacuum": specific lib-versions may be inherited from dependencies (down the dep tree), and changes may require cascading dependency changes (up the dep tree).

The solution

When a package "foo" is obsolete and to be replaced by a package "bar", the maintainer needs to do two things in package "foo":

Provide a clean upgrade path

Package "foo" must still exist as long as other packages use it and/or users might still have it installed. Therefore, one creates a new revision (or version) of it that Depends on whatever package(s) and version(s) now supply its former contents. A user can thus upgrade from his old "foo" to this new one without having to know to install the different package-name.

This package "foo" would be Type:bundle or else some other dummy package format. If not Type:bundle, remember to create a share/doc/%n/README or touch a file share/doc/installed-files/%n, as packages that do not contain any files are forbidden.

Handling user-land executable packages

There might be a reason to keep the actual contents instead of just providing a dummy upgrade package. For example, a certain user-land executable might be in a new package-name but the maintainer wants to keep the old one around for a while. In this situation, one would obviously keep the old package as a real one with contents and not a bundle with Depends on the new one. This does not provide an obvious upgrade path, but the maintainer does not want to make the upgrade mandatory. The best solution might be a DescUsage or DescDetail note about the new package to use instead.

Mark the package as obsolete

To mark the package "foo" as obsolete, list "fink-obsolete-packages" in its Depends field. However, if you are making a splitoff obsolete, then you should use

 RuntimeDepends: fink-obsolete-packages
 BuildDepends: fink (>= 0.32)

instead. Otherwise, building the main package (or any of the non-obsolete splitoffs) will cause fink-obsolete-packages to be installed, which is undesirable. But when using RuntimeDepends, f-o-p gets only installed when a user tries to actually install the obsolete splitoff.

In addition to adding the dependency, you must change the Description field to reflect that the package is obsolete. There are two alternatives here: If your packages has a specific unique successor package 'bar', then use this:

    Description: OBSOLETE use package 'bar' instead

If there is no clear successor, use this (and provide the promised extra information in DescDetail)

    Description: OBSOLETE use 'fink info %n' to learn more

Once you have done this, Fink automatically treats package "foo" as obsolete in several ways:

  • fink cleanup --obsolete-packages will attempt to remove obsolete packages. Due to the upgrade-path dependencies (see above) the user already has the actual new package installed, so the obsolete package is not needed from the user's perspective.
  • When a user needs to choose among several alternative packages to satisfy a dependency, obsolete packages are marked as such and are presented last in the list. This encourages the user to choose the modern package and avoid having the obsolete package installed.
  • When fink is run in --maintainer mode, an error is generated when a package has a dependency that is preferentially satisfied by an obsolete package. This encourages the maintainer to write dependencies on the modern package, avoids forcing users to install the obsolete package, and helps excise the obsolete package from the dependency tree.

There are some special concerns related to headers packages and other situations where a package that is BuildDependsOnly: true becomes obsolete. If foo-dev is renamed to foo1-dev, foo-dev is obsolete and foo1-dev is a normal package with BuildDependsOnly: true. The whole purpose here is for other packages that have a dependency on the old package-name (foo-dev) to behave "correctly" instead of breaking. Thus, foo-dev has Depends:foo1-dev, fink-obsolete-packages. Ordinarily, a dependency on a BDO package is forbidden, however, it is allowed when the dependant package is marked as obsolete. Note that the obsolete package should still be marked with the same BDO tag as the new package, again so that packages that have dependencies on the old package get the correct BDO signals.

The obsoletes mechanism is for packaging changes, not for changes handled by other means such as Shlibs Policy "new package-name for new install_name" situations. You should not obsolete a library or headers package when a new major libversion is packaged. That is, if there was foo1-{dev,shlibs} and then foo2-{dev,shlibs} is added, foo1 is still a completely valid package (and indeed some dependants may never be able to convert to using foo2 because the the lib interface may have changed compared to foo1). Therefore, neither foo1-dev nor foo1-shlibs should be marked as obsolete.