pkgsrc-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[pkgsrc/trunk]: pkgsrc/mk/pkgformat/pkg reduce-depends.awk: Reduce "pkg>1" an...
details: https://anonhg.NetBSD.org/pkgsrc/rev/a04d6c6f038a
branches: trunk
changeset: 369562:a04d6c6f038a
user: jlam <jlam%pkgsrc.org@localhost>
date: Sun Oct 01 04:00:40 2017 +0000
description:
reduce-depends.awk: Reduce "pkg>1" and "pkg<2" into "pkg>1<2".
Enhance the reduce-depends.awk script to reduce a larger set of
dependencies into a single dependency. The patterns representing
intervals of version numbers (can be open-ended) are of the form:
pkg>lower
pkg>=lower
pkg<upper
pkg<=upper
pkg>lower<upper
pkg>lower<=upper
pkg>=lower<upper
pkg>=lower<=upper
These patterns are now condensed into a single dependency of the
same form. For example, given the following patterns:
pkg>=1.0
pkg>2.0
pkg<3.0
pkg<=4.0
pkg>=2.5<3.5
the reduced pattern becomes:
pkg>=2.5<3.0
Add the test script used to help with refactoring and adding the
new feature to the script.
This is a mostly complete rewrite of the script; change the
license to the standard 2-clause BSD license used by TNF.
diffstat:
mk/pkgformat/pkg/reduce-depends.awk | 240 ++++++++++++----
mk/pkgformat/pkg/tests/Kyuafile | 3 +-
mk/pkgformat/pkg/tests/reduce-depends_test | 421 +++++++++++++++++++++++++++++
3 files changed, 601 insertions(+), 63 deletions(-)
diffs (truncated from 758 to 300 lines):
diff -r 2b65d2addda0 -r a04d6c6f038a mk/pkgformat/pkg/reduce-depends.awk
--- a/mk/pkgformat/pkg/reduce-depends.awk Sat Sep 30 21:52:17 2017 +0000
+++ b/mk/pkgformat/pkg/reduce-depends.awk Sun Oct 01 04:00:40 2017 +0000
@@ -1,8 +1,8 @@
#!/usr/bin/awk -f
#
-# $NetBSD: reduce-depends.awk,v 1.4 2017/05/19 14:58:51 joerg Exp $
+# $NetBSD: reduce-depends.awk,v 1.5 2017/10/01 04:00:40 jlam Exp $
#
-# Copyright (c) 2006 The NetBSD Foundation, Inc.
+# Copyright (c) 2006-2017 The NetBSD Foundation, Inc.
# All rights reserved.
#
# This code is derived from software contributed to The NetBSD Foundation
@@ -16,13 +16,6 @@
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
-# 3. All advertising materials mentioning features or use of this software
-# must display the following acknowledgement:
-# This product includes software developed by the NetBSD
-# Foundation, Inc. and its contributors.
-# 4. Neither the name of The NetBSD Foundation nor the names of its
-# contributors may be used to endorse or promote products derived
-# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -43,22 +36,99 @@
# reduce-depends.awk -- reduce a list of dependencies
#
# SYNOPSIS
-# reduce-depends.awk "depends_list"
+# reduce-depends.awk depends-list
#
# DESCRIPTION
# reduce-depends.awk removes some extraneous dependencies from the
# dependency list. The dependency list should be passed as a single
# argument, and the output will be a list of the reduced dependencies,
-# echo one on a new line.
+# each dependency separated by a new line.
+#
+# depends-list A whitespace-separated list of dependencies.
+# This must be passed to the script as a single
+# argument.
#
# ENVIRONMENT
-# CAT
+# CAT The name or path to the cat(1) utility.
+#
# PKG_ADMIN
+# The name or path to the pkg_admin(1) utility.
+#
# PWD_CMD
-# TEST
+# The command to get the physical path to the current
+# working directory. The default is "pwd -P".
+#
+# TEST The name or path to the test(1) utility.
#
######################################################################
+function shquote(s)
+{
+ # Escape single quotes (') by replacing them with '\''.
+ gsub(/'/, "'\\''", s)
+ # Surround with single quotes (').
+ return "'" s "'"
+}
+
+function version_cmp(v1, cmp, v2, cmd, pattern, pkg)
+{
+ pkg = shquote("test-" v1)
+ test_pattern = shquote("test" cmp v2)
+ cmd = PKG_ADMIN " pmatch " test_pattern " " pkg
+ if (system(cmd) == 0) {
+ # v1 "cmp" v2
+ return 1
+ }
+ return 0
+}
+
+###
+# get_endpoint(cmp, patterns)
+#
+# Parameters:
+# cmp (string)
+# The relational operator ("<", "<=", ">", ">=").
+#
+# patterns (array)
+# The keys of the array form the set of dependency
+# patterns that need to be reduced to a single pattern.
+# The patterns all use the relational operator (cmp)
+# and each expresses a ray of version strings. The
+# value associated with each key is the endpoint for
+# that pattern.
+#
+# Return value:
+# endpoint (string)
+# The endpoint for the ray of version strings.
+#
+# Description:
+# Returns a version string that is the endpoint of the ray of
+# version strings formed from the intersection of the rays
+# expressed by the patterns listed in the patterns array.
+#
+function get_endpoint(cmp, patterns, endpoint, key, match_all, pattern, pkg)
+{
+ endpoint = "" # return value if patterns array is empty
+ for (key in patterns) {
+ endpoint = patterns[key]
+ pkg = shquote(gensub(cmp, "-", 1, key))
+ match_all = 1
+ for (pattern in patterns) {
+ if (key == pattern) continue
+ # Fix up the pattern to be closed if it is open.
+ if (cmp == "<") sub("<", "<=", pattern)
+ else if (cmp == ">") sub(">", ">=", pattern)
+ cmd = PKG_ADMIN " pmatch " shquote(pattern) " " pkg
+ if (system(cmd) != 0) {
+ match_all = 0
+ break
+ }
+ }
+ if (match_all == 1) break
+ }
+ return endpoint
+}
+
BEGIN {
CAT = ENVIRON["CAT"] ? ENVIRON["CAT"] : "cat"
PKG_ADMIN = ENVIRON["PKG_ADMIN"] ? ENVIRON["PKG_ADMIN"] : "pkg_admin"
@@ -68,8 +138,12 @@
PROGNAME = "reduce-depends.awk"
ERRCAT = CAT " 1>&2"
- # Gather all dependencies into the depends array. Index 0 of the
- # depends[pkgpath] array is the number of patterns associated with
+ # Match version numbers with an ERE.
+ # XXX This matches more than it should.
+ VERSION_RE = "[0-9A-Za-z._+]+"
+
+ # Gather all dependencies into the patterns array. Index 0 of the
+ # patterns[pkgpath] array is the number of patterns associated with
# that pkgpath.
#
args = ARGV[1]
@@ -81,19 +155,19 @@
print "ERROR: [" PROGNAME "] invalid dependency pattern: " ARGV[i] | ERRCAT
exit 1
}
- if (pattern_seen[pattern] == 1)
- continue
+ if (pattern_seen[pattern] == 1) continue
pattern_seen[pattern] = 1
- cmd = TEST " -d " dir
+ cmd = TEST " -d " shquote(dir)
if (system(cmd) == 0) {
- cmd = "cd " dir " && " PWD_CMD
+ cmd = "cd " shquote(dir) " && " PWD_CMD
while ((cmd | getline pkgpath) > 0) {
if (!(pkgpath in pkgsrcdirs)) {
+ # Record package paths in the order they are seen.
pkgpaths[P++] = pkgpath
pkgsrcdirs[pkgpath] = dir
}
- depends[pkgpath, 0]++;
- depends[pkgpath, depends[pkgpath, 0]] = pattern
+ D = ++patterns[pkgpath, 0]
+ patterns[pkgpath, D] = pattern
}
close(cmd)
} else {
@@ -102,61 +176,103 @@
}
}
- # Reduce dependencies to the strictest set of dependencies it
- # can derive from all of depends[...]. It only understands
- # dependencies of the form foo>=1.0, and leaves the other
- # dependencies undisturbed.
- #
- # 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,
- # will satisfy every dependency.
- #
+ # Reduce dependency patterns by package path.
for (p = 0; p < P; p++) {
pkgpath = pkgpaths[p]
- D = depends[pkgpath, 0];
- match_all = 1;
+ dir = pkgsrcdirs[pkgpath]
+ D = patterns[pkgpath, 0]
for (d = 1; d <= D; d++) {
- dep = depends[pkgpath, d]
- if (dep ~ /[{]/ || \
- dep ~ />=[0-9][0-9\.]*(nb[0-9]+)?<[0-9]+/ || \
- dep !~ />=[0-9]+/)
- {
- reduced[N++] = dep ":" pkgsrcdirs[pkgpath]
- continue
+ # Repeatedly strip off possible boundary conditions to
+ # arrive at the PKGBASE.
+ pattern = patterns[pkgpath, d]
+ lt_bound = ""; le_bound = ""; ge_bound = ""; gt_bound = ""
+ if (match(pattern, "<" VERSION_RE "$")) {
+ lt_bound = substr(pattern, RSTART + 1, RLENGTH)
+ pattern = substr(pattern, 1, RSTART - 1)
+ }
+ if (match(pattern, "<=" VERSION_RE "$")) {
+ le_bound = substr(pattern, RSTART + 2, RLENGTH)
+ pattern = substr(pattern, 1, RSTART - 1)
+ }
+ if (match(pattern, ">" VERSION_RE "$")) {
+ gt_bound = substr(pattern, RSTART + 1, RLENGTH)
+ pattern = substr(pattern, 1, RSTART - 1)
}
- ge_depends[dep] = dep
+ if (match(pattern, ">=" VERSION_RE "$")) {
+ ge_bound = substr(pattern, RSTART + 2, RLENGTH)
+ pattern = substr(pattern, 1, RSTART - 1)
+ }
+ base = pattern
+ if (lt_bound) lt_patterns[base "<" lt_bound] = lt_bound
+ if (le_bound) le_patterns[base "<=" le_bound] = le_bound
+ if (gt_bound) gt_patterns[base ">" gt_bound] = gt_bound
+ if (ge_bound) ge_patterns[base ">=" ge_bound] = ge_bound
+ if (!(lt_bound || le_bound || gt_bound || ge_bound)) {
+ depend = pattern ":" dir
+ if (!(depend in reduced)) reduced[depend] = ++N
+ } else {
+ pkgbase[pkgpath] = base
+ }
}
- for (dep in ge_depends) {
- dep2pkg = dep; sub(">=", "-", dep2pkg)
- match_all = 1
- for (pattern in ge_depends) {
- cmd = PKG_ADMIN " pmatch \"" pattern "\" " dep2pkg
- if (system(cmd) != 0) {
- match_all = 0
- break
- }
+ lt_bound = get_endpoint("<", lt_patterns)
+ le_bound = get_endpoint("<=", le_patterns)
+ gt_bound = get_endpoint(">", gt_patterns)
+ ge_bound = get_endpoint(">=", ge_patterns)
+
+ # Lower bound and relational operator.
+ lower_bound = ""; gt = ""
+ if (gt_bound && ge_bound) {
+ if (version_cmp(gt_bound, ">=", ge_bound)) {
+ lower_bound = gt_bound; gt = ">"
+ } else {
+ lower_bound = ge_bound; gt = ">="
}
- if (match_all == 0) continue
- reduced[N++] = dep ":" pkgsrcdirs[pkgpath]
- break
+ } else if (gt_bound) {
+ lower_bound = gt_bound; gt = ">"
+ } else if (ge_bound) {
+ lower_bound = ge_bound; gt = ">="
}
- #
+
+ # Upper bound and relational operator.
+ upper_bound = ""; lt = ""
+ if (lt_bound && le_bound) {
+ if (version_cmp(lt_bound, "<=", le_bound)) {
+ upper_bound = lt_bound; lt = "<"
+ } else {
+ upper_bound = le_bound; lt = "<="
+ }
+ } else if (lt_bound) {
+ upper_bound = lt_bound; lt = "<"
+ } else if (le_bound) {
+ upper_bound = le_bound; lt = "<="
+ }
+
# If there are conflicting dependencies, then just pass them
# through and let the rest of the pkgsrc machinery handle it.
#
- if (match_all == 0) {
+ # Othewise, build a new dependency based on the intersection
+ # of the rays determined by the various bounds.
+ #
+ if (lower_bound && upper_bound &&
+ ((gt == ">" && version_cmp(lower_bound, ">=", upper_bound)) ||
+ (gt == ">=" && version_cmp(lower_bound, ">", upper_bound)))) {
for (d = 1; d <= D; d++) {
- dep = depends[pkgpath, d]
- reduced[N++] = dep ":" pkgsrcdirs[pkgpath]
+ depend = patterns[pkgpath, d] ":" dir
+ if (!(depend in reduced)) reduced[depend] = ++N
}
+ } else if (lower_bound || upper_bound) {
+ pattern = pkgbase[pkgpath] gt lower_bound lt upper_bound
Home |
Main Index |
Thread Index |
Old Index