I've tried to make a first attempt at resolving dependency loops using the specific dependency type as hint for ordering.
The patch attached will try attempt resolving the loops by removing one kind of dependency type (based on what seems likely to be the most important kind of dependency wrt. ordering, correctness is probably not 100% here), then rescanning for still existing loops, then remove next kind of dependency, then rescan and on... Dunno if this seems like a sane enough approach or not (or whether implemented in the correct place or not), but it seems like a step in the right direction at least. :) WDYT? -- Regards, Per Øyvind
--- lib/order.c 2011-01-25 16:05:02.287333979 +0100 +++ /home/peroyvind/RPM/rpm/BUILD/rpm-5.3.8/lib/order.c 2011-02-01 18:33:06.607553037 +0100 @@ -332,7 +332,7 @@ static inline /*@observer@*/ const char /*@-mustmod@*/ /* FIX: hack modifies, but -type disables */ static /*@owned@*/ /*@null@*/ const char * zapRelation(rpmte q, rpmte p, - int zap, /*@in@*/ /*@out@*/ int * nzaps, int msglvl) + int zap, /*@in@*/ /*@out@*/ int * nzaps, int msglvl, rpmuint32_t skipFlags) /*@globals rpmGlobalMacroContext, h_errno, internalState @*/ /*@modifies q, p, *nzaps, rpmGlobalMacroContext, internalState @*/ { @@ -361,6 +361,8 @@ zapRelation(rpmte q, rpmte p, (void) rpmdsSetIx(requires, tsi->tsi_reqx); Flags = rpmdsFlags(requires); + if(Flags & skipFlags) + continue; dp = rpmdsNewDNEVR( identifyDepend(Flags), requires); @@ -369,8 +371,8 @@ zapRelation(rpmte q, rpmte p, */ if (zap) { rpmlog(msglvl, - _("removing %s \"%s\" from tsort relations.\n"), - (rpmteNEVRA(p) ? rpmteNEVRA(p) : "???"), dp); + _("removing %s \"%s\" from tsort relations.\n"), + (rpmteNEVRA(p) ? rpmteNEVRA(p) : "???"), dp); rpmteTSI(p)->tsi_count--; if (tsi_prev) tsi_prev->tsi_next = tsi->tsi_next; tsi->tsi_next = NULL; @@ -1812,6 +1814,18 @@ int _rpmtsOrder(rpmts ts) int depth; int breadth; int qlen; + static const evrFlags orderPriority[] = { + RPMSENSE_MISSINGOK, + RPMSENSE_SCRIPT_VERIFY, + RPMSENSE_PACKAGE, + RPMSENSE_FIND_REQUIRES, + _ERASE_ONLY_MASK, + _INSTALL_ONLY_MASK, + _ALL_REQUIRES_MASK + }; /* dependency to zap in order to try resolve dependency loops */ + rpmuint32_t skipFlags = _ALL_REQUIRES_MASK; + unsigned sfi = 0; + #endif /* REFERENCE */ if (_rpmts_debug) @@ -2007,6 +2021,9 @@ fprintf(stderr, "--> %s(%p) tsFlags 0x%x rescan: if (pi != NULL) pi = rpmtsiFree(pi); #endif + if (sfi < sizeof(orderPriority)) + skipFlags &= ~orderPriority[sfi++]; + q = r = NULL; qlen = 0; pi = rpmtsiInit(ts); @@ -2168,10 +2185,14 @@ rescan: const char * nevra; #endif const char * dp; + /* + * TODO: use RPMLOG_DEBUG for when loops can be resolved + * without zapping all dependencies in it + */ rpmlogLvl msglvl = (anaconda || (rpmtsDFlags(ts) & RPMDEPS_FLAG_DEPLOOPS)) ? RPMLOG_WARNING : RPMLOG_ERR; #if defined(RPM_VENDOR_MANDRIVA) /* loop-detection-optional-loglevel */ - // Report loops as debug-level message by default (7 = RPMLOG_DEBUG), overridable + /* Report loops as debug-level message by default (7 = RPMLOG_DEBUG), overridable */ msglvl = rpmExpandNumeric("%{?_loop_detection_loglevel}%{?!_loop_detection_loglevel:7}"); #endif @@ -2184,7 +2205,7 @@ rescan: } /* Find (and destroy if co-requisite) "q <- p" relation. */ - dp = zapRelation(q, p, 1, &nzaps, msglvl); + dp = zapRelation(q, p, 1, &nzaps, msglvl, skipFlags); #if 0 /* Print next member of loop. */