RFC: pkg-order -- Specs and design
Hi folks,
Here is the requirements/specifications and design document
for pkg-order. I delayed posting this hoping to upload a conformant
copy of pkg-order, but that might have to wait for a little bit as I
test the large number of small changes I've been making.
Oh, I now have a cgi version of a dependency checker / package
ordering system, which depends on wget to get the installed and new
files ;-)
Any feedback, flames, encouragement, etc is welcome.
manoj
===========================================================================
Requirements
------------
* The package should write out an order to install new packages
* The package should be able to detect dependency loops in the new
package list.
* The package should be able to work stand alone, however, it should
provide libraries so that the dependency checks and topological
sorts on new packages are available to other scripts/programs as
well. (like dftp, auto build a whole distribution from scratch,
other dependency checkers).
* The package should be a user interface only, all functionality
should be wrapped into the libraries so that alternate user
interfaces would be easy (using ncurses, perltk, dialog, CGI, etc
one can have multiple front ends).
* The package should make no assumptions about the fields in the
package description, except possibly fields that it needs for
operation (Package, Status, Pre-Depends, Depends, Recommends,
Suggests, Conflicts, and Replaces).
* The package should also be able to do dependency satisfaction checks
on other relationship fields in the package (Recommends, and
Suggests) as well, if asked by the user.
* The package should use dpkg and friends to do version checks rather
than hard coding it internally -- (in case things change, like the
recent introduction of epochs).
* The package should be able to read installed packages from
/var/lib/dpkg/status -- or one or more files in the samefomat
supplied by the user (*must* have the status field)
* The package should be aware of virtual packages.
* The package (or at least the libraries underneath) should provide an
easy means of adding/deleting packages to the list of packages to be
installed.
* This package should do nothing else than produce an ordering list
(apart from error messages about failed dependency checks, and
information asked by the user). It should not modify anything, apart
from maybe temp files in /tmp.
* The package should be flexible about handling anomalies (a failed
dependency check could cause the process to stop, or the package
that failed the dependency (or conflict) to be marked as failed, and
ignored from further processing, and a ordering generated for the
rest of the packages.
* The package should offer configurable levels of verbosity and debug
messages.
Nice qualities of the current implementation:
---- --------- -- --- ------- --------------
* One should be able to run it as a ordering tool, a dependency
checker, or both.
* One may pass in the installed files as a comma separated list to the
application, but if you roll your own app, using the library, you
could process the installed files one by one, marking failed new
packages on each run. Finally, one could just run the ordering pass
on the packages that survive (you could do this in one fell swoop,
if you wish, as well, as the code is written).
Inputs:
------
* The new packages list -- the packages to be installed.
* The list of installed packages -- the packages on the system
* The virtual packages list
The current implementation of the ordering tool reads the new
packages list from a Package file given on the command line, and the
installed packages list from /var/lib/dpkg/status (ignoring packages
in status that are not installed ok), and uses the built in list of
virtual packages, unless given an alternative on the command
line. Also there an option of specifying a comma separated list of
Package files as installed packages, or another option to specify a
comma separated list of status files.
The underlying Library supports adding packages to the list
one at a time (we split up the Packages file internally anyway), by
supplying a string containing the output of dpkg --info or dpkg
-s. In fact the test method supplies a made up package info string to
add a package for a test.
Process:
-------
In the checking dependency phase, for each package in
the new packages list, we look at the dependencies, and ensure that
each dependency is satisfied in either the new packages list or the
installed list.
* Test Pre-Dependencies. (add to package order info; need to keep
this static)
failures: mark packages not to be processed anymore.
Default action: exit on any error
Optionally: dynamically ignore package, mark as failed,
continue.
* Test Conflicts:
failures: mark packages not to be processed anymore.
Default action: continue
Need to handle conflict and replace: remove mark if we also replace.
That is, a conflict is bad, but a conflict *AND* a replacement of
the same package should be fine. Merely replacing a package
with another is also not a problem.
Optionally: fail hard.
* Test Recommends: (optional)
failures: message, Default: do not mark and do not exit
* Test Suggests: (optional)
failures: message, Default: do not mark and do not exit
* Test Dependencies:
failures: mark packages not to be processed anymore.
Default action: exit on any error
The ordering action is tied to this step. If the directive is
satisfied from the new packages list, a line is added to the
ordering info with the format
<package-that-needs-to-be-installed-first> <current-package>
The information is later printed to an output file, and then we
run tsort on the output file, giving us an order to install new
packages in.
Responses to failures:
--------- -- --------
The user should be able to run any or all of these steps;
Failure at any step should be configurable Responses could be
1) stop
2) mark package as bad
3) warn verbosely, but no mark.
4) Summarize number of failures
5) ignore (same as not running this step)
5 possible runs, each with 5 error Responses.
Classe Hierarchy:
------ ---------
*)Debian::Package::Virtual
This class handles the list of legal virtual packages, initialized
from a space separated list of virtual package names, or by a static
built in list valid at the time of writing.
Data Structures:
Associative array keyed on virtual package name (associative
array was choosen for ease of determonong membership)
methods:
new: Initializer
print: Prints the list of virtual Packages
is_member: Checks if argument is a member of the list.
add: Adds a package name to the list
test: Tests the package.
*)Debian::Package::List
This class handles lists of packages. It creates an associative array
of Debian::Package:Package objects, keyed on package name. The most
common entry point takes in Packages files. It also records packages
which are provided; provided packages do not figure in package
ordering,
Data Structures:
Associative array
methods:
new: Initializer This takes a named parameter, filename,
which should be the path of a Packages file to use as the
data for the list.
check : virtual functions to be instantiated in the
extra : derived classes.
print: loops through the packages in the list, calling the
print function of each package object.
print_name: Like prit, but just prints package names.
add: Adds a package to the list
test: Tests the package.
*@)Debian::Package::Installed
This is a sub class derived from Debian::Package:List, it takes in
/var/lib/dpkg/status unless given Packages files of installed
packages. Handles Status fields.
methods:
new: Initializer defaults Packages file to
/var/lib/dpkg/status
check: Reject packages with a status field that is not \
ok installed ok.
test: Tests the package.
*@)Debian::Package::New
This is a sub class derived from Debian::Package:List, all dependency
and ordering runs are started on the list of new packages.
methods:
extra: As an extra processing of every package, creates a
dependeny list object for various fields.
check_relations: performs the dependency checks and/or package
ordering for the new packages.
print_order: Write out the order information from all packages
which do not have a failed tag to a file (specify
fields to be considered -- Pre-Depends, Depends, etc)
tsort: Run tsort on the given file. (How hard is it to
write a topological sort in perl?)
test: Tests the package.
**)Debian::Package::Package:
This class handles information about a Debian Package. It initializes
the package details with a snippet of a Packages file, and also
creates and manipulates internal fileds by creating fileds names
starting with a blank and underscore ' _'. Additional Fields
correspond to dependeny list object for the fields Depends,
Pre-Depends, Recommends, Suggests, Conflicts, and Replaces.
Also, the ordering information for a package is kept in '
_Order'. and the status (Success and Failure information) is also
maintained here.
Data Structures:
Associative array keyed on Field name. The values of internal
fileds need not be simple strings.
methods:
new: Initializer It takes an required argument, which is a
snippet from the Packages file.
print takes the key value pairs that constitute a Package
definition and prints it out.
print_failure: Print causes for failures (unsatisfied
dependencies, conflicts, etc). Takes in a
keyword for the field (Pre-Depends, Depends,
etc)
failure_as_string: As above, except it returns a string.
check_failure: As above, except it returns a count.
print_success: Print satisfied dependencies etc. Takes in a
keyword for the field (Pre-Depends, Depends,
etc).
success_as_string: As above, except it returns a string.
check_success: As above, except it returns a count.
print_conflict: Print Conflicts for this package.
conflict_as_string: As above, except it returns a string.
check_conflict: As above, except it returns a count.
print_order: Return a string containing the order information
from all dependencies for a particular field for
every dependency in the list.
test: Tests the package.
***)Debian::Package::Dependency_List
This class implements a dependency list object. It is expected
that one Debian::Package::Dependency_List object shall be created
for each of the relationship fields in a package description.
Data Structures:
Associative array keyed on the package name of the package we
depend on. Handles the or `|' operator (used to denote
alternates, and, the most desirable package .
methods:
new: Initializer It takes an required named argument, string,
whose value is the value of the Pre-Depends, Dependes,
Recommends, Suggests, Conflicts, or Replaces field values
for the package. argument, which is a snippet from the
Packages file.
add Adds a new dependency to the list.
match: This method takes a dependency object as an argument,
compares it with all the dependencies in the list, and
returns 'Yes' if there is a match.
print takes the internal representation of a dependency list
(complete with alternatives) and produces a string,
which should be the string used to initialize the
object.
depend: This method performs dependency checks for all
elements of the dependency list. It takes required
named argument Package, which is the package object
to whom this dependency list belongs. It cycles
through all dependencies, calling the depend method of
each dependency object, handling alternates as it
goes.
order: Return the order information from all dependencies in
the list.
test: Tests the package.
****)Debian::Package::Dependency
This module implements a Debian::Package::Dependency object, which
contains Meta info for a single dependency.
Data Structures:
Associative array
methods
new: Initializer It takes a named argument, string, whose
value is the value of an element in a dependecy
list. This is a fancy way of saying we record the name,
relationship, and version number of the package we have a
relationship with, with only the name being required. The
relation ship is one of = << <= >>, or >=.
match: This method takes a dependency object as an argument,
compares it with self, and return 'Yes' if they are
identical.
print: This method takes the internal representation of a
dependency and prints it.
as_string This method takes the internal representation of a
dependency and converts it into a string
depend This method takes Named package lists New and
Installed, and check self to see if the dependencies
are satisfied. It first checks the package list new,
and then the package list installed.
order: Return the order information for this dependency
test: Tests the package.
--
"Floggings will continue until morale improves." anonymous flyer
being distributed at Exxon USA
Manoj Srivastava <url:mailto:srivasta@acm.org>
Mobile, Alabama USA <url:http://www.datasync.com/%7Esrivasta/>
--
TO UNSUBSCRIBE FROM THIS MAILING LIST: e-mail the word "unsubscribe" to
debian-devel-REQUEST@lists.debian.org . Trouble? e-mail to Bruce@Pixar.com
Reply to: