Subject: dependencies showing up twice
To: None <tech-pkg@NetBSD.org>
From: Klaus Heinz <k.heinz.mai.sieben@kh-22.de>
List: tech-pkg
Date: 05/21/2007 03:31:41
--E39vaYmALEf/7YXx
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi,

for some time I have seen output on the screen showing package dependencies
twice during the "depends" phase. Until today I have never cared about this.

The problem always shows up for dependency specifications like
foo-[0-9]*:../../category/foo or {foo,...}:../../category/foo but never
for simple ones like foo>=3:../../category/foo.

After finding my way through the awk script reduce-depends.awk I think
what happens is this:

  The dependency patterns ("foo>=4") are stored in a two-dimensional array
  depends[] indexed first by the pkgsrc path for a package and second by a
  numerical index.

  All dependency patterns for a path are scanned for comparability, only
  ">=" patterns are comparable. The other patterns are stored as they
  are in the array reduced[], to be printed at the end.

  A search for the strictest pattern, encompassing all the other patterns,
  is then done among the remaining comparable patterns in array ge_depends[].

  If no "best" pattern can be found, because for a specific path the patterns
  conflict with at least one of the others (eg, foo>=3 and foo2>=4, for a
  pkgsrc path category/foo) all of them have to be returned, just as the
  uncomparable ones (not of the form ">=") above.

  After a conflict is detected (ie (match_all == 0) is true outside the
  "for" loop) _all_ of the dependencies for a pkgsrc path are put into
  array reduced[] which is then printed as the output of reduce-depends.awk.
  This disregards the fact that reduced[] might already contain uncomparable
  dependencies.
  Patterns like "foo-[0-9]*" or "{foo,...}" are of the uncomparable
  sort, so if a package only depends on patterns like this, they are put
  twice into the arry reduced[].

  The solution for this wrong behaviour is to put only the comparable
  patterns from ge_depends[] into the array reduced[]. All the others
  were weeded out before and already contained in the array.

The appended patch makes the problem go away for me. Some added comments
may prove helpful to understand what's going on.

ciao
     Klaus

--E39vaYmALEf/7YXx
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="reduce-depends.awk.diff"

Index: reduce-depends.awk
===================================================================
RCS file: /cvsroot/pkgsrc/mk/flavor/pkg/reduce-depends.awk,v
retrieving revision 1.3
diff -u -r1.3 reduce-depends.awk
--- reduce-depends.awk	6 Jun 2006 20:05:44 -0000	1.3
+++ reduce-depends.awk	21 May 2007 01:27:36 -0000
@@ -96,23 +96,27 @@
 	# The algorithm takes dependencies of the form foo>=1.0 and
 	# converts them to foo-1.0.  It then compares this pkg name against
 	# each dependency to see if it satisfies them all.  The key fact
-	# is the the strictest dependency, when converted to a pkg name,
+	# is that the strictest dependency, when converted to a pkg name,
 	# will satisfy every dependency.
 	#
 	for (p = 0; p < P; p++) {
 		pkgpath = pkgpaths[p]
 		D = depends[pkgpath, 0];
+		# weed out dependencies of a form we cannot compare
 		for (d = 1; d <= D; d++) {
 			dep = depends[pkgpath, d]
 			if (dep ~ /[{]/ || \
 			    dep ~ />=[0-9]+<[0-9]+/ || \
 			    dep !~ />=[0-9]+/)
-			{
+			{ # leave this dependency undisturbed
 				reduced[N++] = dep ":" pkgsrcdirs[pkgpath]
 				continue
 			}
 			ge_depends[dep] = dep
 		}
+		# Among the dependencies of interest to us for this path,
+		# let's find one matching all the others.
+		#
 		for (dep in ge_depends) {
 			dep2pkg = dep; sub(">=", "-", dep2pkg)
 			match_all = 1
@@ -124,16 +128,19 @@
 				}
 			}
 			if (match_all == 0) continue
+
+			# Found the strictest dependency. We're done here
 			reduced[N++] = dep ":" pkgsrcdirs[pkgpath]
 			break
 		}
-		#
-		# If there are conflicting dependencies, then just pass them
-		# through and let the rest of the pkgsrc machinery handle it.
+
+		# If there is no winner matching all of the comparable
+		# dependencies due to conflicts (eg foo>=1.0 and foo2>=2.0
+		# for path bla/foo) then just pass all of them through and
+		# let the rest of the pkgsrc machinery handle it.
 		#
 		if (match_all == 0) {
-			for (d = 1; d <= D; d++) {
-				dep = depends[pkgpath, d]
+			for (dep in ge_depends) {
 				reduced[N++] = dep ":" pkgsrcdirs[pkgpath]
 			}
 		}

--E39vaYmALEf/7YXx--