Story #2637

As a user, I'm able to import Debian packages with their dependencies represented correctly.

Added by 11 days ago. Updated 9 days ago.

% Done:


Platform Release:
Blocks Release:
Target Release - Debian:
Backwards Incompatible:
Sprint Candidate:
QA Contact:
Smash Test:
Verification Required:


Pulp currently represents Requires and Provides for rpm packages as lists of dictionaries:

:ivar provides: List of packages/libraries this package provides. Each entry is a
dictionary with the "release", "epoch", "version", "flags", and "name"
:type provides: list of dict

:ivar requires: List of packages/libraries this package requires. Each entry is a dictionary
with the "release", "epoch", "version", "flags", and "name" field.
:type requires: list of dict

flags is one of None, EQ, LT, LE, GT, GE.

Debian package dependencies are "different". They support version comparisons, just like rpm packages. In addition to that, they support architecture matching (positive or negative), build profile matching (positive or negative). They also support disjunction (I want python2 or python3).

The python-debian library has a deb822 module that will parse these dependencies and return some format that I don't want to store directly in pulp, because it's far too distant from what we have in rpm.

Here is the documentation from deb822:

def relations(self):
"""Return a dictionary of inter-package relationships among the current
and other packages.

Dictionary keys depend on the package kind. Binary packages have keys
like 'depends', 'recommends', ... while source packages have keys like
'build-depends', 'build-depends-indep' and so on. See the Debian policy
for the comprehensive field list.

Dictionary values are package relationships returned as lists of lists
of dictionaries (see below for some examples).
The encoding of package relationships is as follows:
- the top-level lists corresponds to the comma-separated list of
Deb822, their components form a conjunction, i.e. they have to be
AND-ed together
- the inner lists corresponds to the pipe-separated list of Deb822,
their components form a disjunction, i.e. they have to be OR-ed
- member of the inner lists are dictionaries with the following keys:
- name: package (or virtual package) name
- version: A pair <operator, version> if the relationship is
versioned, None otherwise. operator is one of "<<",
"<=", "=", ">=", ">>"; version is the given version as
a string.
- arch: A list of pairs <enabled, arch> if the
relationship is architecture specific, None otherwise.
Enabled is a boolean (false if the architecture is
negated with "!", true otherwise), arch the
Debian architecture name as a string.
- restrictions: A list of lists of tuples <enabled, profile>
if there is a restriction formula defined, None
otherwise. Each list of tuples represents a restriction
list while each tuple represents an individual term
within the restriction list. Enabled is a boolean
(false if the restriction is negated with "!", true
otherwise). The profile is the name of the build

The arch and restrictions tuples are available as named tuples so
elements are available as term0 or alternatively as
term.enabled (and so forth).


"emacs | emacsen, make, debianutils (>= 1.7)" becomes
[ [ {'name': 'emacs'}, {'name': 'emacsen'} ],
[ {'name': 'make'} ],
[ {'name': 'debianutils', 'version': ('>=', '1.7')} ] ]

"tcl8.4-dev, procps [!hurd-i386]" becomes
[ [ {'name': 'tcl8.4-dev'} ],
[ {'name': 'procps', 'arch': (false, 'hurd-i386')} ] ]

"texlive <!cross>" becomes
[ [ {'name': 'texlive',
'restriction': [[(false, 'cross')]]} ] ]

I personally don't like the list of (disjunction of lists) representation, given that it's a relatively uncommon case. Also, I don't like breaking out the arch and profile as tuples just to represent positive or negative matches.

My proposal is to reuse as much as possible from Yum's syntax. Like so:

  • single package is a dictionary, conjunction is a list of packages (i.e. dictionaries).
  • flag represents the operator of the relationship if one exists, and use the same string values as rpm: GT, GE, LT, LE, EQ. arch
  • arch is a list of one or more strings. Negation is represented with a leading exclamation mark
  • restriction, if present, is a list of one or more strings, with the same meaning as arch.

So, for the examples in the deb822 package:

"emacs | emacsen, make, debianutils (>= 1.7)" 
deb822: [ [ {'name': 'emacs'}, {'name': 'emacsen'} ], [ {'name': 'make'} ], [ {'name': 'debianutils', 'version': ('>=', '1.7')} ] ]
pulp: [ [{'name': 'emacs'}, {'name': 'emacsen'} ], {'name': 'make'}, {'name': 'debianutils', 'version': '1.7', 'flag': 'GE'} ]
"tcl8.4-dev, procps [!hurd-i386]" 
deb822: [ [ {'name': 'tcl8.4-dev'} ], [ {'name': 'procps', 'arch': (false, 'hurd-i386')} ] ]
pulp: [ {'name': 'tcl8.4-dev'}, {'name': 'procps', 'arch': ['!hurd-i383']} ]
"texlive <!cross>" 
deb822: [ [ {'name': 'texlive', 'restriction': [[(false, 'cross')]]} ] ]
pulp: [ {'name': 'texlive', 'restriction': ['!cross']} ]


#1 Updated by bizhang 9 days ago

  • Tracker changed from Issue to Story
  • Priority changed from Normal to Low
  • % Done set to 0

#2 Updated by bizhang 9 days ago

  • Subject changed from Debian dependencies represented in pulp to As a user, I'm able to import Debian packages with their dependencies represented correctly.

@misa would you mind updating this story with the functional details? [0]

Let me know if you think this isn't a new feature and I should convert it to a task instead


Please register to edit this issue

Also available in: Atom PDF