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. */

Reply via email to