RPM Community Forums

Mailing List Message of <rpm-devel>

Re: Trying to understand RPM 5 vs RPM 4 "Conflicts" handling

From: Jeff Johnson <n3npq@mac.com>
Date: Thu 10 Apr 2008 - 16:53:49 CEST
Message-Id: <9A3D0813-EE6B-4A73-9999-75416656A3A7@mac.com>

On Apr 10, 2008, at 8:29 AM, devzero2000 wrote:

>
> Also this reference could be useful, besides that something is  
> based on some rpm patch not upstream, imho:
> http://en.opensuse.org/Upgrade_Dependencies
>
>
> What do you think ?
>

Let me speak to the general issue(s) first. The issue of a self- 
conflicting
package that cannot be installed will be obvious when the time comes.

We all agree that creating a package that cannot be installed serves
no purpose. But we likely disagree, possibly strongly, on how to do
an implementation that "naturally" and "obviously" prevents incoherent
logical assertions like
	Provides: foo
	Conflicts: foo

The core issue (for me) is the domain used for assertion checking of
dependencies. We all agree that Requires: match Provides:, and if  
there is a match,
then a dependency is satisfied, and if no match, unsatisfied.

But matching needs to supply missing data to be evaluated. How should
	Requires: foo
and
	Requires: foo = 1.2-3
be evaluated, with similar issues for Provides: and other dependency  
matching.

For historical reasons, rpm chose matching to supply missing data was  
any/all.
That means that
	Requires: foo
is matched by any/all
	Provides: foo
The historical part is due to leqacy compatibity with rpm-2 with  
unversioned Provides:.

WIth the above choices (and a well defined comparison algorithm), a  
logically consistent
assertion checker can be (and has been) devised for rpm.
(aside) There are other choices than any/all that could have been  
chosen when
versioned Provides: were added to rpm-3.0.2 in order to generalize  
assertion checking.
The other choices were considered at the time, and "any/all" was chosen.

The next part of establishing an evaluation framework for package  
dependencies
is choosing explicit identifiers for package objects. Originally the  
Name: tag was used,
a perfectly obvious choice. However, even in 2000 there were issues  
with package
renaming and "compatibility". In order to accomodate these needs in  
rpm, the Name: tag value
was duplicated into a Provides: so the rule that we all (apparently)  
agree with
      Requires: should match Provides:
could be consistently continued. There are additional benefits with  
using Provides:
instead of Name: as one of the matching elements, namely packages can  
have multiple
explicit names.

There's one other incidental issue that was introduced into rpm with  
mutually exclusive
packages. At some point "capabilities" were added to packages to  
accomodate functionally
equivalent, but intrinsically mutually exclusive implementations. The  
classic example is
sendmail <-> postfix, both of which carried
     Provides: smtpdaemon
As other mail transport packages were attempted, there were requests  
for removal-by-capability,
specifically (in the case of sendmail) for the ability to  
automatically replace all other
pre-existing mutually exclusive "capabilities" using
     Obsoletes: smtpdaemon
I point out the history above (that everyone should know already)  
largely because
the choices above are what need to be changed if you _REALLY_ want a
fix. Any other fix will not address the fundamental issues that are  
buried in
the choices above.

(aside) I add from the URL you provided specific points where "SuSE  
Package Management"
specifically has decided to disagree with RPM:

=======================================
Facts for RPM dependencies

Each package implicitly provides its name.
There is no need to provide the package name, but other packages can  
require (or conflict with) the package name.
A package can not conflict with a symbolic tag it provides.
Since the package name is provided implicitly, a package can not  
conflict with itself.
Obsolete works on real package names only.
One can not obsolete a symbolic tag.
Symbolic names, as used in Requires, Provides, and Conflicts, are  
case-sensitive
=======================================

These are reversions (both FACTS and RPM are confusing) introduced by  
SuSE for SuSE reasons.
SImilar reversions to RPM have been made in Fedora's rpm-4.4.2, whose  
rpm now differs in behavior
from RHEL3/RHEL4/RHEL5. Note carefully that I have said "different",  
not better, worse or anything
else. Different behavior is a flaw no matter what, I'm sure we can  
all agree on that. Note that SuSE
and Fedora have changed, not RPM itself. Changing RPM is certainly  
possible, but the fundamental
design chocies are what need to be changed, not reverted for some  
narrower goal.

Since SuSE has a clearer (and sounder, I understand the choices  
perfectly)) statement of its intents than
Fedora, let me respond with several observations.

1) package naming needs to accomodate UTF-8 as well as %{dist}/% 
{repo} tag renaming and rebranding.

     There is already a Fedora proposal to permit UTF-8 package names  
for display purposes. There have
      been years of discussions about various "branding" issues that  
involve package name changes.
      Several "feature" requests to convert --query output for  
display purposes have been made over
      the last 2 years as well, including several patches from SuSE too.

      My conclusion: package NEVR (and A and O) usage within rpm for  
anything but identification
      purposes needs to be avoided and phased out.

2) conflicts, which lead to full-stop install termination, with  
associated support issues diagnosing/correcting
the problem, are costly for users and vendors.

      Conflicts: have ugly behavior. Sure Conflicts: can be used  
intelligently and usefully. But the basic
      flaw remains: costly. Installs stop, users get annoyed, support  
infrastructure is necessary, all the
      usual baggage. My personal opinion is that Conflicts: should be  
avoided if at all possible, there
      are usually better solutions available if you think more  
carefully about the packaging problem.

     My conclusion: mechanisms for automatically resolving, not full  
stop termination on assertion failure,
     need to be implemented.

3) stronger semantics need to be tied to "symbolic names"

      Much like the "Provides: smtpdaemon" capability, representing  
capabilities with strings is useful
      iff the underlying mechanism and purpose are well defined and  
testable. Imagining a "capability"
      and adding to packaging is rather easy to do, insuring that the  
mechanism that implements what
      the capability represents is, in fact, in place is a much  
harder task.

      My conclusion: a richer, and finer-grained, capability name  
space, with explictly testable behavior,
      not just whether strings match, is needed.

So let me to summarize the points relevant to the much narrower topic  
of avoiding self-conflcting
packages:

1) dependencies like
     Provides: foo
are too broad and poorly defined to be useful in packaging. A better  
approach is to narrow the
range to, say
     Provides: foo = E:V-R
(which has a point measure) or to a
     Provides: foo <= E:V-R
(which has a well defined measure). That is especially true when  
retrofitting a virtual provides
for compatibility.

2) Obsoletes, rather than Conflicts, based on capabilty, not package  
name, should be used
where possible. That is specifically true for avoiding self- 
conflicting packages as well.

Now that the general context (I was asked "intentions") has been  
dealt with, can we get back
to trying to avoid self-conflicting packages?

Presumably we all still agree that creating a package that cannot be  
installed is useless.

First submitted reproducer that I can achieve in my build environment  
will get my immediate attention.

73 de Jeff


  
    
Received on Thu Apr 10 16:55:22 2008
Driven by Jeff Johnson and the RPM project team.
Hosted by OpenPKG and Ralf S. Engelschall.
Powered by FreeBSD and OpenPKG.