Subject: Ranges support for pkg_install
To: None <tech-pkg@NetBSD.org>
From: Thomas Klausner <wiz@NetBSD.org>
List: tech-pkg
Date: 05/27/2005 00:51:21
--uQr8t48UFsdbeI+V
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi!

The attached patch adds version number ranges support to the
pkg_install tools.

The initial consumer will be audit-packages (after the next branch)
and a few packages that already need it, but work around it, can
be converted to use it too.

The syntax is a direct extension of what we currently have:
"foo>=1.3<2.0" will match package foo, versions 1.3 (inclusive) to
2.0 (exclusive).  Of course, > and <= also work, but the lower
bound has to come first.

Diff attached (with some related const poisoning).
Comments?
 Thomas & Dillo

--uQr8t48UFsdbeI+V
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="pkg_install-ranges.diff"

Index: info/pkg_info.1
===================================================================
RCS file: /cvsroot/src/usr.sbin/pkg_install/info/pkg_info.1,v
retrieving revision 1.48
diff -u -r1.48 pkg_info.1
--- info/pkg_info.1	18 Apr 2005 12:28:46 -0000	1.48
+++ info/pkg_info.1	26 May 2005 22:24:02 -0000
@@ -17,7 +17,7 @@
 .\"
 .\"     @(#)pkg_info.1
 .\"
-.Dd February 10, 2005
+.Dd May 27, 2005
 .Dt PKG_INFO 1
 .Os
 .Sh NAME
@@ -210,6 +210,15 @@
 will match versions 1.3 and later of the
 .Pa name
 package.
+Additionally, ranges can be defined by giving a lower bound with
+\*[Gt] or \*[Ge] and an upper bound with \*[Lt] or \*[Le].
+The lower bound has to come first.
+For example,
+.Pa pkg_info -e 'name\*[Ge]1.3\*[Lt]2.0'
+will match versions 1.3 (inclusive) to 2.0 (exclusive)
+of package
+.Pa name .
+.Pp
 The collating sequence of the various package version numbers is
 unusual, but strives to be consistent.
 The magic string
Index: lib/str.c
===================================================================
RCS file: /cvsroot/src/usr.sbin/pkg_install/lib/str.c,v
retrieving revision 1.50
diff -u -r1.50 str.c
--- lib/str.c	29 Dec 2004 11:35:04 -0000	1.50
+++ lib/str.c	26 May 2005 22:24:02 -0000
@@ -163,7 +163,7 @@
 
 /* locate the test in the tests array */
 static int
-mktest(int *op, char *test)
+mktest(int *op, const char *test)
 {
 	const test_t *tp;
 
@@ -188,12 +188,12 @@
  * 'nb' encodes as 'netbsd version', which is used after all other tests
  */
 static int
-mkcomponent(arr_t *ap, char *num)
+mkcomponent(arr_t *ap, const char *num)
 {
 	static const char       alphas[] = "abcdefghijklmnopqrstuvwxyz";
 	const test_t	       *modp;
 	int64_t                 n;
-	char                   *cp;
+	const char             *cp;
 
 	if (*num == 0) {
 		return 0;
@@ -232,7 +232,7 @@
 
 /* make a version number string into an array of comparable 64bit ints */
 static int
-mkversion(arr_t *ap, char *num)
+mkversion(arr_t *ap, const char *num)
 {
 	(void) memset(ap, 0, sizeof(arr_t));
 	while (*num) {
@@ -286,7 +286,7 @@
  * Compare two dewey decimal numbers
  */
 static int
-deweycmp(char *lhs, int op, char *rhs)
+deweycmp(const char *lhs, int op, const char *rhs)
 {
 	arr_t	right;
 	arr_t	left;
@@ -359,31 +359,59 @@
 static int
 dewey_match(const char *pattern, const char *pkg)
 {
-	char   *cp;
-	char   *sep;
-	char   *ver;
-	char    name[MaxPathSize];
-	int	op;
-	int     n;
-
-	if ((sep = strpbrk(pattern, "<>")) == NULL) {
-		errx(EXIT_FAILURE, "dewey_match(): '<' or '>' expected in `%s'", pattern);
+	const char *version;
+	const char *sep, *sep2;
+	int op, op2;
+	int n;
+
+	/* compare names */
+	if ((version=strrchr(pkg, '-')) == NULL) {
+		warnx("Invalid package name `%s'", pkg);
+		return 0;
 	}
-	(void) snprintf(name, sizeof(name), "%.*s", (int) (sep - pattern), pattern);
+	if ((sep = strpbrk(pattern, "<>")) == NULL)
+		errx(EXIT_FAILURE, "dewey_match: '<' or '>' expected in `%s'", pattern);
+	/* compare name lengths */
+	if ((sep-pattern != version-pkg) ||
+	    strncmp(pkg, pattern, (size_t)(version-pkg)) != 0)
+		return 0;
+	version++;
+	
+	/* extract comparison operator */
         if ((n = mktest(&op, sep)) < 0) {
                 warnx("Bad comparison `%s'", sep);
 		return 0;
         }
-	ver = sep + n;
-	n = (int) (sep - pattern);
-	if ((cp = strrchr(pkg, '-')) != (char *) NULL) {
-		if (strncmp(pkg, name, (size_t) (cp - pkg)) == 0 &&
-		    n == (int)(cp - pkg)) {
-			if (deweycmp(cp + 1, op, ver)) {
-				return 1;
+	/* skip operator */
+	sep += n;
+
+	/* if greater than, look for less than */
+	sep2 = NULL;
+	if (op == GT || op == GE) {
+		if ((sep2 = strchr(sep, '<')) != NULL) {
+			if ((n = mktest(&op2, sep2)) < 0) {
+				warnx("Bad comparison `%s'", sep2);
+				return 0;
 			}
+			/* compare upper limit */
+			if (!deweycmp(version, op2, sep2+n))
+				return 0;
 		}
 	}
+
+	/* compare only pattern / lower limit */
+	if (sep2) {
+		char ver[PKG_PATTERN_MAX];
+
+		strlcpy(ver, sep, MIN(sizeof(ver), sep2-sep+1));
+		if (deweycmp(version, op, ver))
+			return 1;
+	}
+	else {
+		if (deweycmp(version, op, sep))
+			return 1;
+	}
+
 	return 0;
 }
 
Index: lib/version.h
===================================================================
RCS file: /cvsroot/src/usr.sbin/pkg_install/lib/version.h,v
retrieving revision 1.65
diff -u -r1.65 version.h
--- lib/version.h	18 Mar 2005 00:12:35 -0000	1.65
+++ lib/version.h	26 May 2005 22:24:02 -0000
@@ -33,6 +33,6 @@
 #ifndef _INST_LIB_VERSION_H_
 #define _INST_LIB_VERSION_H_
 
-#define PKGTOOLS_VERSION "20050318"
+#define PKGTOOLS_VERSION "20050527"
 
 #endif /* _INST_LIB_VERSION_H_ */

--uQr8t48UFsdbeI+V--